﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using QQZiFramework.Membership;
using QQZiFramework.Membership;

namespace QQZiFramework
{

    public delegate Type CreateBusinessHandle(DBContext context, Type t);

    public delegate void DataUpdatingHandle(DBContext context, IDBEntity entity, bool isCreateNew);

    public delegate void DataDeletingHandle(DBContext context, Type entityType, object primaryValue);

    public class DBContext : IDisposable
    {

        public static event DataUpdatingHandle OnEntityUpdated;
        public static event DataDeletingHandle OnEntityDeleted;

        [Obsolete("请直接重写Membership.CreateServiceInstance")]
        public static event CreateBusinessHandle OnBusinessCreating;

        /// <summary>
        /// 依赖注入的服务
        /// </summary>
        public static IServiceProvider ServiceProvider { get; set; }

        internal static IMemoryCache Cache
        {
            get
            {
                return ServiceProvider.GetService(typeof(IMemoryCache)) as IMemoryCache;
            }
        }

        public TItem GetOrCreateCache<TItem>(string key, Func<ICacheEntry, TItem> factory)
        {
            key = membership.OnCacheKey(key);
            return Cache.GetOrCreate(key, factory);
        }

        static List<Type> m_updatingWatchs = new List<Type>();

        public static void AddWatch(Type type)
        {
            if (m_updatingWatchs.IndexOf(type) == -1)
            {
                m_updatingWatchs.Add(type);
            }
        }

        private static DBContextConfig GlobalDBContextConfig;

        /// <summary>
        /// 日志数据库的配置，空则与默认的相同
        /// </summary>
        public static DBContextConfig LogDBConfig { get; set; }

        private DBContextConfig currentDBContextConfig;

        public DBContextConfig GetConfig()
        {
            DBContextConfig config = currentDBContextConfig == null ? GlobalDBContextConfig : currentDBContextConfig;
            if (config == null) throw new ClientException("没有相关配置，全局请使用DBContext.LoadConfig");
            return config;
        }

        //访问销的列表，用HasLock访问
        private static Dictionary<string, object> lockQueue = new Dictionary<string, object>();

        /// <summary>
        /// 是否使用redis缓存用户、代理商等信息
        /// </summary>
        public static bool UserRedis;

        //private static readonly object Locker = new object(); 


        private bool useTran = false;

        ///// <summary>
        ///// 初始化Redis配置
        ///// </summary>
        ///// <param name="host"></param>
        ///// <param name="port"></param>
        //[Obsolete("请使用RedisAccess.SetRedis")]
        //public static void SetRedis(string host, int port, string pwd, int pool = 5, bool log = true)
        //{
        //    UserRedis = true;
        //    RedisAccess.SetRedis(new RedisConfig { IP = host, Port = port, Password = pwd, Log = log, MinPool = pool });

        //}


        List<RedisAccess> _redisAccessList = new List<RedisAccess>();

        private static int default_redis_index = -1;

        /// <summary>
        /// 默认的redis数据库索引,GetRedisDatabase方法不传值的时候用,不指定则默认为第一个数据库
        /// </summary>
        public static int Default_Redis_Database_Index
        {
            get
            { return default_redis_index; }
            set
            {
                default_redis_index = value;
                if (DBIdentity_Redis_Database_Index == -1) DBIdentity_Redis_Database_Index = value;
            }
        }

        /// <summary>
        /// 表自增主键redis
        /// </summary>
        public static int DBIdentity_Redis_Database_Index = -1;

        /// <summary>
        /// 获取redis访问操作
        /// </summary>
        /// <param name="index">数据库索引（RedisDBName类）</param>
        /// <returns></returns>
        public RedisAccess GetRedisDatabase(int index = -1)
        {
            int dataBaseIndex = index == -1 ? Default_Redis_Database_Index : index;
            RedisAccess _redisAccess = _redisAccessList.Find(x => x.DataBaseIndex == dataBaseIndex);
            if (_redisAccess == null)
            {
                // this.LogMessage("create redis access of database : " + dataBaseIndex, "redis");
                _redisAccess = new RedisAccess(this);
                _redisAccess.DataBaseIndex = dataBaseIndex;
                _redisAccessList.Add(_redisAccess);
            }
            return _redisAccess;
        }

        #region Redis
        public T GetRedisItem<T>(string key, bool throwNull = true)
        {
            return GetRedisDatabase().GetRedisItem<T>(key, throwNull);
        }
        public Dictionary<string, T> FindRedis<T>(string pattern)
        {
            return GetRedisDatabase().FindRedis<T>(pattern);
        }
        public void SetRedisItem(string key, object item, DateTime? expiresAt = null)
        {
            GetRedisDatabase().SetRedisItem(key, item, expiresAt);
        }

        public long IncrementRedisItem(string key)
        {
            return GetRedisDatabase().IncrementRedisItem(key);
        }

        public void DeleteRedisItem(string key)
        {
            GetRedisDatabase().DeleteRedisItem(key);
        }

        #endregion

        /// <summary>
        /// 等待锁
        /// </summary>
        /// <param name="lockItem">锁名称，不能与其它锁同名</param>
        /// <param name="seconds">超时毫秒数</param>
        /// <returns>等待毫秒数</returns>
        public int WaitLock(string lockItem, int seconds)
        {
            int waitLimit = seconds / 1000;//HasLock检查一次如果有锁，会等1S
            int count = 0;
            while (HasLock(lockItem))
            {
                count++;
                if (count > waitLimit) break;
            }
            return count * 1000;
        }

        /// <summary>
        /// 是否有设置访问锁（不允许同时访问using进程，特别是用在异步回调）
        /// </summary>
        /// <param name="lockItem">锁名称，不能与其它锁同名</param>
        /// <returns></returns>
        public bool HasLock(string lockItem)
        {
            SqlLogMode current = this.LogSql;
            this.LogSql = SqlLogMode.NoLog;
            bool haslocak = false;
            //Redlock.CSharp.Lock lockObject = null;
            for (int i = 0; i < 5; i++)
            {
                if (UserRedis)
                {
                    string aa = GetRedisItem<string>(lockItem, false);
                    haslocak = aa != null;
                }
                else haslocak = lockQueue.ContainsKey(lockItem);
                if (haslocak)
                {
                    System.Threading.Thread.Sleep(200);
                }
                else break;
            }
            if (haslocak)
            {
                this.LogSql = current;
                return true;
            }
            else
            {

                if (UserRedis)
                {
                    // if (current_lockItems == null) current_lockItems = new Dictionary<string, Redlock.CSharp.Lock>();
                    // current_lockItems.Add(lockItem, lockObject);
                    SetRedisItem(lockItem, "1", DateTime.Now.AddMinutes(5)); //使用Redis.Lock，最多锁定5分钟
                    if (current_lockItems == null) current_lockItems = new List<string>();
                    current_lockItems.Add(lockItem);
                }
                else lockQueue.Add(lockItem, true);
                this.LogSql = current;
                return false;
            }
        }
        //Dictionary<string, Redlock.CSharp.Lock> current_lockItems;//当前过程设置的访问销，在dispose时释放用
        List<string> current_lockItems; //当前过程设置的访问销，在dispose时释放用
        /// <summary>
        /// 载入配置
        /// </summary>
        /// <param name="json">配置json值，可以从文件中读取完传入</param>
        /// <param name="entityTypeFormater">全局用：实体类全名格式化,比如Nd.CheckList.ArgumentDiscuss.{0}, CheckListService</param>
        public static void LoadConfig(DBContextConfig config)
        {
            if (config == null) GlobalDBContextConfig = new DBContextConfig();
            else GlobalDBContextConfig = config;
            //if (LogDBConfig == null) LogDBConfig = config;
            //   queryMapping = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, QueryEntityConfig>>(json);

        }

        // static string permissionPath;
        // /// <summary>
        // /// 重载入配置文件
        // /// </summary> 
        // public static void ReloadConfig()
        // {
        //     string json = ReadFile(permissionPath);
        //     if (string.IsNullOrEmpty(json)) queryMapping = new Dictionary<string, QueryEntityConfig>();
        //     else queryMapping = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, QueryEntityConfig>>(json);
        // }


        private static Type membershipUserType = null; //, cookieUserType = null;

        private static IMembership defaultMembership;
        IMembership membership;

        /// <summary>
        /// 用户状态存储类型（0,1：cookie  2:session 3:静态变量)
        /// </summary>
        public IMembership Membership
        {
            get
            {
                if (defaultMembership == null) throw new Exception("请在启动的时候调用DBContext.RegistMembership");
                if (membership == null) membership = defaultMembership;
                return membership;
            }
        }

        public T GetSettingValue<T>(string path, bool throwNoFoundError = false, T defaultVal = default(T))
        {
            return Membership.GetSettingValue<T>(this, path, throwNoFoundError, defaultVal);
        }

        /// <summary>
        /// 注册使用哪个Membership（web应用，桌面应用等用户存储等方式不一样）
        /// </summary>
        /// <param name="stateType">保存方式</param>
        /// <param name="userType">用户类型</param>
        public static void RegistMembership(IMembership membershipBLL)
        {
            defaultMembership = membershipBLL;
            membershipUserType = membershipBLL.UserType;
        }

        //public static Dictionary<string, QueryEntityConfig> queryMapping;

        QueryEntityConfig qEntity = null;

        IDBAccess m_dbAccess;


        public IDBAccess GetDBAccess()
        {
            if (m_dbAccess == null)
            {
                string key = GetConfig().DatabaseType.ToLower();
                switch (key)
                {

                    case "sqlserver":
                    case "mssql":
                    case "system.data.sqlclient":
                        m_dbAccess = new QQZiFramework.DataBase.SqlClient.SqlAccess(this);
                        break;
                    default:
                        string dllFile = GetConfig().DatabaseType;
                        if (dllFile == "mysql") dllFile = "QQZiFramework.DataBase.MySql";//兼容早期配置
                        if (!dllFile.EndsWith(".dll")) dllFile += ".dll";
                        var dicPath = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                        dllFile = System.IO.Path.Combine(dicPath, dllFile);
                        if (!System.IO.File.Exists(dllFile)) throw new Exception("数据库ProviderName=" + dllFile + "文件加载失败，请检查文件是否存在！");
                        Assembly assembly = Assembly.LoadFile(dllFile);
                        if (assembly == null) throw new Exception(dllFile + "加载失败");
                        Type interfaceType = typeof(IDBAccess);
                        try
                        {
                            foreach (var t in assembly.GetTypes())
                            {
                                if (interfaceType.IsAssignableFrom(t))
                                {
                                    m_dbAccess = System.Activator.CreateInstance(t, this) as IDBAccess;
                                    break;
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            throw new Exception("加载" + dllFile + "发生异常，请核对版本号及依赖:" + ex.Message);
                        }

                        if (m_dbAccess == null) throw new Exception("创建数据访问实例失败，请检查是否有继承IDBAccess");

                        break;
                }
                m_dbAccess.Create(GetConfig().ConnectionString);
            }
            return m_dbAccess;
        }

        private void InitDBContext(bool useTrans, string dbType, string conn, string formater, IMembership membership)
        {

            if (dbType != null || conn != null || formater != null)
            {
                currentDBContextConfig = new DBContextConfig
                {
                    ConnectionString = conn == null ? GlobalDBContextConfig.ConnectionString : conn,
                    DatabaseType = string.IsNullOrEmpty(dbType) ? GlobalDBContextConfig.DatabaseType : dbType,
                    EntityTypeFormat = formater == null ? GlobalDBContextConfig.EntityTypeFormat : formater,
                    AlwayQueryCount = GlobalDBContextConfig.AlwayQueryCount
                };
            }
            if (GlobalDBContextConfig == null) throw new Exception("在创建实例前,请先使用LoadConfigFromFile初始化DBContext");
            LogSql = GlobalDBContextConfig.LogSql;
            this.useTran = useTrans;
            if (membership != null)
            {
                membership.OnDBContextInit(this);
                this.membership = membership;
                if (membership is IBusiness)
                {
                    IBusiness bll = (IBusiness)membership;
                    bll.SetVisiter(this);
                    this.businessList.Add(bll);
                }
            }

        }

        /// <summary>
        /// 创建实体
        /// </summary>
        /// <param name="dbType">数据库类型(sqlserver,mysql,oracle)</param>
        /// <param name="conn">连接串</param>
        /// <param name="formater">实体类全名的格式化，空则使用全局的</param>
        public DBContext(string dbType, string conn, string formater)
        {
            InitDBContext(false, dbType, conn, formater, null);
        }
        public DBContext(string dbType, string conn, string formater, IMembership membership, Hashtable args)
        {
            Arguments = args;
            InitDBContext(false, dbType, conn, formater, membership);

        }

        public DBContext(string formater)
        {
            InitDBContext(false, null, null, formater, null);

        }
        //public DBContext(bool useTrans)
        //{
        //    InitDBContext(useTrans, null, null, null);
        //}
        public DBContext()
        {
            InitDBContext(false, null, null, null, null);
        }

        /// <summary>
        /// 记录sql语句的方式，0：不记录，1：记录除select之外的，2：全部，实例化的时候会使用全局配置
        /// </summary>
        public SqlLogMode LogSql { get; set; }

        /// <summary>
        /// 记录sql到日志
        /// <param name="isQuery">是否为查询语句</param>
        /// </summary>
        public void LogSqlMessage(string sql, bool isQuery)
        {
            bool isLog = false;
            switch (LogSql)
            {
                case SqlLogMode.All:
                    isLog = true;
                    break;
                case SqlLogMode.ExceptSelect:
                    isLog = !isQuery;
                    break;
            }
            if (isLog) LogMessage(sql, "SQL");
            //else System.Diagnostics.Debug.WriteLine(sql);
        }

        string stepMsg = null;

        /// <summary>
        /// 记录异常Log4Net
        /// </summary>
        /// <param name="ex"></param>
        public static void UnHandleException(Exception ex)
        {
            if (defaultMembership != null)
            {
                defaultMembership.LogException(ex, "system", null);
            }
        }

        /// <summary>
        /// 记录异常Log4Net
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="moduleName"></param>
        public void LogException(Exception ex, string moduleName = null)
        {
            if (ex == null) return;
            Membership.LogException(ex, moduleName, this);
        }


        public void LogMessage(string message, string moduleName = null)
        {
            if (message == null) return;
            // if (message.IndexOf("A0_LogEvents") > -1) return; //不保存记录日志的语句
            Membership.LogMessage(message, moduleName, this);
        }

        public void LogDebug(string message, string moduleName = null)
        {
            if (message == null) return;
            Membership.LogDebug(message, moduleName, this);
        }

        /// <summary>
        /// 查询单条数据，以DataTable返回
        /// </summary>
        public DataTable DoGetOneTable(string permission, string entityName, string primarkVal, string queryFilter = "*")
        {

            return DoQuery(ConvertPrimaryQueryParam(permission, entityName, primarkVal, queryFilter));
        }

        /// <summary>
        /// 将根据主键的查询转换为QueryParam
        /// </summary>
        /// <returns></returns>
        public QueryParam ConvertPrimaryQueryParam(string permission, string entityName, string primarkVal, string queryFilter = "*")
        {
            QueryParam param = new QueryParam() { entityName = GetFullName(entityName), permission = permission, queryField = queryFilter };
            param.InitParam(GetConfig().EntityTypeFormat, this);
            param.AddWhere(param.LoaderInfo.PrimaryCusPro.Info.Name, primarkVal);
            return param;
        }
        /// <summary>
        /// 将根据主键的查询转换为QueryParam
        /// </summary>
        public QueryParam ConvertPrimaryQueryParam(string permission, Type entityType, string primarkVal, string queryFilter = "*")
        {
            QueryParam param = new QueryParam() { entityType = entityType, permission = permission, queryField = queryFilter };
            param.InitParam(GetConfig().EntityTypeFormat, this);
            param.AddWhere(param.LoaderInfo.PrimaryCusPro.Info.Name, primarkVal);
            return param;
        }

        ///// <summary>
        ///// 查询单条数据，以DataTable返回
        ///// </summary>
        //public DataTable DoGetOneTable(QueryParam param)
        //{

        //    return DoQuery(param);
        //}

        /// <summary>
        /// 获取类型的全名
        /// </summary>
        /// <param name="_entityName"></param>
        public string GetFullName(string _entityName)
        {
            if (_entityName == null) throw new ArgumentNullException("entityName");
            string typeFullName;
            if (_entityName.IndexOf('.') > 1) typeFullName = _entityName;
            else typeFullName = string.Format(GetConfig().EntityTypeFormat, _entityName);
            return typeFullName;

        }

        public string GetFullName(Type type)
        {
            return type.FullName + "," + type.Assembly.FullName;
        }

        ///// <summary>
        ///// 查询单条数据，以IDBEntity返回
        ///// </summary>
        ///// <param name="param">查询参数，包含实体类型，不包含条件</param>
        ///// <param name="primarkVal">主键</param>
        ///// <param name="throwWhen">为空是抛出异常</param>
        ///// <param name="clearDefaultNull">值类型属性为空时是否清除DefaultNullValue（不赋值-999999）</param>
        ///// <returns></returns>
        //public IDBEntity DoGetOne(QueryParam param, string primarkVal, string throwWhen, bool clearDefaultNull)
        //{
        //    param.InitParam(GetConfig().EntityTypeFormat, this);
        //    CustomerProperty attr = GetPrimary(param.entityType);
        //    //param.ClientWhere = null;//手动将ClientWhere置空，因为InitParam会初始化，导致不能再设置whereJson
        //    param.AddWhere(attr.Info.Name, primarkVal);
        //    return DoGetOne(param, throwWhen, clearDefaultNull);
        //}

        /// <summary>
        /// 查询单条数据，以IDBEntity返回
        /// </summary>
        /// <param name="param">查询参数，包含实体类型，条件</param>
        /// <param name="throwWhen">为空是抛出异常</param>
        /// <returns></returns>
        public IDBEntity DoGetOne(QueryParam param, string throwWhen)
        {
            if (param.entityType == null) param.InitParam(GetConfig().EntityTypeFormat, this);
            DataTable dt = DoQuery(param);
            if (dt.Rows.Count > 0)
            {
                if (dt.Rows.Count > 1) throw new ClientException("查询" + param.entityType.Name + "返回多条结果");
                stepMsg = "查询结束，Create " + param.entityType.Name + " Instance";
                IDBEntity entity = (IDBEntity)System.Activator.CreateInstance(param.entityType, false);
                stepMsg = "ParseFromTable";
                //if (clearDefaultNull) { entity.ClearDefaultValue(); }
                entity.ParseFromTable(dt);
                return entity;
            }
            else
            {
                if (throwWhen != null)
                {
                    if (throwWhen == "") throwWhen = "找不到" + param.entityType.Name + "记录";
                    throw new ClientException(throwWhen);
                }
                return null;
            }
        }

        /// <summary>
        /// 查询并返回单个实体
        /// </summary>
        /// <param name="permission">配置项名称</param>
        /// <param name="entityName">实体名,非默认命名空间则使用全类名</param>
        /// <param name="primarkVal">主键值</param>
        /// <param name="queryFilter">查询列（实体属性）过滤，以逗号隔开</param>
        /// <param name="throwWhen">没有数据是否抛异常,Null：不抛，空字符串则抛出默认的消息，也可以是传具体的消息内容</param>
        /// <param name="parseDefault">是否使用DefaultValue来更新属性值（使用DefaultValue自定义属性）</param>
        /// <returns></returns>
        public IDBEntity DoGetOne(string permission, string entityName, string primarkVal, string queryFilter, string throwWhen, bool strictModel = false)
        {
            QueryParam param = ConvertPrimaryQueryParam(permission, entityName, primarkVal, queryFilter);
            param.StrictModel = strictModel;
            return DoGetOne(param, throwWhen);
        }

        /// <summary>
        /// 查询并返回单个实体,空数值则使用defaultNullValue
        /// </summary>        
        /// <param name="primarkVal">主键值</param>
        /// <param name="queryFilter">查询列（实体属性）过滤，以逗号隔开</param>        
        /// <param name="throwWhen">没有数据是否抛异常,Null：不抛，空字符串则抛出默认的消息，也可以是传具体的消息内容</param>
        public T QuerySingle<T>(string primarkVal, string queryFilter, string throwWhen) where T : IDBEntity
        {
            QueryParam param = ConvertPrimaryQueryParam(null, typeof(T), primarkVal, queryFilter);
            return (T)DoGetOne(param, throwWhen);
        }

        /// <summary>
        /// 查询并返回单个实体,空数值则使用defaultNullValue
        /// </summary>        
        /// <param name="primarkVal">主键值</param>
        /// <param name="throwWhen">没有数据是否抛异常,Null：不抛，空字符串则抛出默认的消息，也可以是传具体的消息内容</param>
        public T QuerySingle<T>(string primarkVal, string throwWhen = null) where T : IDBEntity
        {
            QueryParam param = ConvertPrimaryQueryParam(null, typeof(T), primarkVal, null);
            return (T)DoGetOne(param, throwWhen);
        }

        /// <summary>
        /// 查询并返回单个实体,空数值则使用defaultNullValue
        /// </summary>        
        /// <param name="primarkVal">主键值</param>
        /// <param name="throwWhen">没有数据是否抛异常</param>        
        public T QuerySingle<T>(int primarkVal, string throwWhen = null) where T : IDBEntity
        {
            QueryParam param = ConvertPrimaryQueryParam(null, typeof(T), primarkVal.ToString(), null);
            return (T)DoGetOne(param, throwWhen);
        }

        public T QuerySingle<T>(int? primarkVal, string throwWhen = null) where T : IDBEntity
        {
            QueryParam param = ConvertPrimaryQueryParam(null, typeof(T), primarkVal.ToString(), null);
            return (T)DoGetOne(param, throwWhen);
        }

        public T QuerySingle<T>(Int64 primarkVal, string throwWhen = null) where T : IDBEntity
        {
            QueryParam param = ConvertPrimaryQueryParam(null, typeof(T), primarkVal.ToString(), null);
            return (T)DoGetOne(param, throwWhen);
        }

        public T QuerySingle<T>(Int64? primarkVal, string throwWhen = null) where T : IDBEntity
        {
            QueryParam param = ConvertPrimaryQueryParam(null, typeof(T), primarkVal.ToString(), null);
            return (T)DoGetOne(param, throwWhen);
        }

        ///// <summary>
        ///// 查询并返回单个实体
        ///// </summary>        
        ///// <param name="primarkVal">主键值</param>
        ///// <param name="throwWhen">没有数据是否抛异常,Null：不抛，空字符串则抛出默认的消息，也可以是传具体的消息内容</param>
        ///// <param name="defaultNullValue">使用自定义属性DefaultNullValue</param>        
        //public T QuerySingle<T>(int primarkVal, string throwWhen, bool defaultNullValue) where T : IDBEntity
        //{
        //    QueryParam param = new QueryParam() { entityType = typeof(T), permission = null, queryField = null };
        //    return (T)DoGetOne(param, primarkVal.ToString(), throwWhen, !defaultNullValue);
        //}

        /// <summary>
        /// 查询并返回单个实体,空数值则使用defaultNullValue
        /// </summary>        
        /// <param name="primarkVal">主键值</param>
        /// <param name="queryFilter">查询列（实体属性）过滤，以逗号隔开</param>        
        /// <param name="throwWhen">没有数据是否抛异常,Null：不抛，空字符串则抛出默认的消息，也可以是传具体的消息内容</param>
        /// <returns></returns>
        public T QuerySingle<T>(int primarkVal, string queryFilter, string throwWhen, bool? strictModel = null) where T : IDBEntity
        {
            QueryParam param = ConvertPrimaryQueryParam(null, typeof(T), primarkVal.ToString(), queryFilter);
            param.StrictModel = strictModel;
            return (T)DoGetOne(param, throwWhen);
        }

        // /// <summary>
        // /// 查询并返回单个实体,默认使用defaultNullValue
        // /// </summary>
        // /// <param name="permission">配置项名称</param>
        // /// <param name="primarkVal">主键值</param>
        // /// <param name="queryFilter">查询列（实体属性）过滤，以逗号隔开</param>
        // /// <param name="throwWhen">没有数据是否抛异常,Null：不抛，空字符串则抛出默认的消息，也可以是传具体的消息内容</param>
        // /// <param name="defaultNullValue">值类型属性为空是否标记为DefaultNullValue</param>
        // /// <returns></returns>
        // public T QuerySingle<T>(string permission, int primarkVal, string queryFilter, string throwWhen, bool defaultNullValue = true) where T : IDBEntity
        // {
        //     QueryParam param = ConvertPrimaryQueryParam(permission, typeof(T), primarkVal.ToString(), queryFilter);
        //     return (T)DoGetOne(param, throwWhen);
        // }

        /// <summary>
        /// 查询并返回单个实体,空数值则使用defaultNullValue
        /// </summary>      
        /// <param name="permission"></param>
        /// <param name="primarkVal">主键值</param>
        /// <param name="queryFilter">查询列（实体属性）过滤，以逗号隔开</param>        
        /// <returns></returns>
        public T QuerySingle<T>(string permission, int primarkVal, string queryFilter = "*") where T : IDBEntity
        {
            QueryParam param = ConvertPrimaryQueryParam(permission, typeof(T), primarkVal.ToString(), queryFilter);
            return (T)DoGetOne(param, "");
        }

        /// <summary>
        /// 查询并返回单个实体,空数值则使用defaultNullValue
        /// </summary>        
        /// <param name="where">where对象（动态类）</param>
        /// <param name="permission"></param>
        /// <param name="queryFilter">查询列（实体属性）过滤，以逗号隔开</param>        
        /// <param name="throwWhen">没有数据是否抛异常,Null：不抛，空字符串则抛出默认的消息，也可以是传具体的消息内容</param>
        /// <returns></returns>
        public T QuerySingle<T>(object where, string permission, string queryFilter, string throwWhen, bool? strictModel = false) where T : IDBEntity
        {
            if (where == null) return null;
            if (where is QueryParam) throw new Exception("where 参数为条件，请不要传入QueryParam");
            Type entityType = typeof(T);
            QueryParam param = new QueryParam() { StrictModel = strictModel, entityType = entityType, permission = permission, queryField = queryFilter };
            if (where != null) param.SetWhere(where);
            DataTable dt = DoQuery(param);
            if (dt.Rows.Count == 0)
            {
                if (throwWhen != null)
                {
                    if (throwWhen == "") throwWhen = "查询" + entityType.Name + "结果为空";
                    throw new ClientException(throwWhen);
                }
                return null;
            }
            if (dt.Rows.Count > 1) throw new ClientException("查询" + typeof(T).Name + "返回多条结果");
            stepMsg = "查询结束，Create " + entityType.Name + " Instance";
            T entity = System.Activator.CreateInstance(entityType, false) as T;
            stepMsg = "ParseFromTable";
            entity.ParseFromTable(dt);
            return entity;
        }

        public T QuerySingle<T>(object where, bool? strictModel = false) where T : IDBEntity
        {
            return QuerySingle<T>(where, null, null, null, strictModel);
        }

        /// <summary>
        /// 执行语句，返回单个对象
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="sql">语句</param>
        /// <param name="throwWhen">如果没有记录或者有多条是否异常</param>
        /// <returns></returns>
        public T QuerySingleSql<T>(string sql, string throwWhen) where T : IDBEntity
        {
            DataTable dt = GetDBAccess().QueryTable(sql);
            if (dt.Rows.Count > 0)
            {
                if (dt.Rows.Count > 1) throw new ClientException("查询" + typeof(T).Name + "返回多条结果");
                T entity = (T)System.Activator.CreateInstance(typeof(T), false);
                entity.ParseFromTable(dt);
                return entity;
            }
            else
            {
                if (throwWhen != null)
                {
                    if (throwWhen == "") throwWhen = "找不到" + typeof(T).Name + "记录";
                    throw new ClientException(throwWhen);
                }
                return null;
            }

        }

        // QueryEntityInstance queryInstance;
        // public QueryEntityInstance GetInstance()
        // {
        //     if (queryInstance == null) throw new Exception("queryInstance未初始化，请先执行SetQueryEntityConfig方法");
        //     return queryInstance;
        // }

        public bool PermissionConfig_Exists(string permission, string fieldName = null)
        {
            var queryMapping = this.Membership.GetPermissionQueryMapping(this);
            QueryEntityConfig item;
            if (!queryMapping.TryGetValue(permission, out item))
            {
                return false;
            }
            if (fieldName != null)
            {
                if (item.Fields == null || !item.Fields.ContainsKey(fieldName)) return false;
            }
            return true;
        }

        /// <summary>
        /// 初始化查询实例，读取配置，格式化参数
        /// </summary>
        /// <param name="param"></param>
        private QueryEntityInstance SetQueryEntityConfig(QueryParam param)
        {
            if (param.StrictModel == null) param.StrictModel = QueryParam.DefaultStrictModel;
            qEntity = null;
            var queryMapping = this.Membership.GetPermissionQueryMapping(this);
            if (param.permission != null && !queryMapping.TryGetValue(param.permission, out qEntity))
            {
                throw new ClientException("找不到配置的Permission:" + param.permission);
            }
            if (qEntity == null)
            {
                // if (param.StrictModel.Value) throw new ClientException("严格模式已启用，但是配置项" + param.permission + "不存在！");
                stepMsg = "Create A New QueryEntity";
                qEntity = QueryEntityConfig.Create(param.permission);
            }
            if (qEntity.Fields == null) qEntity.Fields = new Dictionary<string, string[]>();
            if (qEntity.NotAllowQuery == null) qEntity.NotAllowQuery = new string[0];
            if (qEntity.NotAllowSaving == null) qEntity.NotAllowSaving = new string[1] { "*" };
            if (qEntity.Fields == null) qEntity.Fields = new Dictionary<string, string[]>();
            // int waitCount = 0;
            // while (queryInstance != null && queryInstance.Lock)
            // {
            //     if (waitCount > 60)
            //     {
            //         throw new Exception("等待释放queryInstance超时，通常是因为多线程使用同一DBContext，或者在Try的过程中执行数据库异常Catch中没有调用LogException");
            //     }
            //     else
            //     {
            //         waitCount++;
            //         if(waitCount==1) System.Diagnostics.Debug.WriteLine("等待释放queryInstance");
            //         System.Threading.Thread.Sleep(500);
            //     }
            // }
            var queryInstance = new QueryEntityInstance() { Config = qEntity, Param = param };
            queryInstance.Lock = true;
            param.InitParam(GetConfig().EntityTypeFormat, this);
            if (param.StrictModel.Value && qEntity.Defaults != null)
            {
                //添加默认查询where
                foreach (KeyValuePair<string, string> ki in qEntity.Defaults)
                {
                    param.AddWhere(ki.Key, ki.Value);
                }
            }
            Thread.SetData(Thread.GetNamedDataSlot("queryInstance"), queryInstance);
            return queryInstance;


        }



        /// <summary>
        /// 通用查询,多表关联以及条件表达式请在json文件中配置
        /// </summary>
        /// <param name="param">查询参数（permission:权限和表达式配置,queryField:查询的字段，客户端实体的名称，逗号隔开,entityType:查询的对象,whereField：查询条件json，比如{aa:'1',dtime:'1,2'} ）</param>        
        public DataTable DoQuery(QueryParam param)
        {

            stepMsg = "解析QueryParam";
            var queryInstance = SetQueryEntityConfig(param);
            return ParseQueryTable(queryInstance);

        }

        public List<IDBEntity> DoQueryEntity(QueryParam param)
        {
            stepMsg = "解析QueryParam";
            var queryInstance = SetQueryEntityConfig(param);
            DataTable dt = ParseQueryTable(queryInstance);
            List<IDBEntity> lst = new List<IDBEntity>();
            foreach (DataRow dr in dt.Rows)
            {
                IDBEntity entity = (IDBEntity)System.Activator.CreateInstance(param.entityType, false);
                entity.ParseFromTableRow(dr);
                lst.Add(entity);
            }
            return lst;
        }
        public DataTable QueryTable<T>(object where, string queryFilter, string permission, bool? strictModel = null) where T : IDBEntity
        {
            QueryParam param = new QueryParam() { entityType = typeof(T), queryField = queryFilter, permission = permission, StrictModel = strictModel };
            if (where != null) param.SetWhere(where);
            stepMsg = "解析QueryParam";
            var queryInstance = SetQueryEntityConfig(param);
            return ParseQueryTable(queryInstance);

        }

        // public DataTable QueryTable<T>(object where, string permission = null) where T : IDBEntity
        // {
        //     return QueryTable<T>(where, null, permission);
        // }

        // public DataTable QueryTable(string entityName, object where, string permission = null)
        // {
        //     QueryParam param = new QueryParam() { entityName = GetFullName(entityName), permission = permission };
        //     if (where != null) param.SetWhere(where);
        //     stepMsg = "解析QueryParam";
        //     var queryInstance = SetQueryEntityConfig(param);
        //     string sql;
        //     return ParseQueryTable(queryInstance, out sql, true);
        // }

        // /// <summary>
        // /// 查询结果返回List
        // /// </summary>
        // /// <param name="sql">查询的语句</param>
        // /// <returns></returns>
        // [Obsolete("已弃用，改为QueryManySql")]
        // public List<T> QueryMany<T>(string sql) where T : IDBEntity
        // {
        //     DataTable dt = GetDBAccess().QueryTable(sql);
        //     List<T> lst = new List<T>();
        //     foreach (DataRow dr in dt.Rows)
        //     {
        //         T entity = (T)System.Activator.CreateInstance(typeof(T), false);
        //         entity.ParseFromTableRow(dr);
        //         lst.Add(entity);
        //     }
        //     return lst;
        // }
        /// <summary>
        /// 查询结果返回List
        /// </summary>
        /// <param name="sql">查询的语句</param>
        /// <returns></returns>
        public List<T> QueryManySql<T>(string sql) where T : IDBEntity
        {
            DataTable dt = GetDBAccess().QueryTable(sql);
            List<T> lst = new List<T>();
            foreach (DataRow dr in dt.Rows)
            {
                T entity = (T)System.Activator.CreateInstance(typeof(T), false);
                entity.ParseFromTableRow(dr);
                lst.Add(entity);
            }
            return lst;
        }

        /// <summary>
        /// 返回第一条
        /// </summary>
        /// <param name="where">查询条件（动态类）</param>
        /// <param name="permission">配置项名称</param>
        /// <param name="queryFilter">查询列（实体属性）过滤，以逗号隔开</param>
        public T QueryTopOne<T>(object where, bool? strictModel = null, string orderBy = null, string permission = null, string queryFilter = null) where T : IDBEntity
        {

            stepMsg = "解析where json";
            QueryParam param = new QueryParam() { orderBy = orderBy, queryField = queryFilter, entityType = typeof(T), permission = permission, StrictModel = strictModel };
            if (where != null) param.SetWhere(where);
            param.Page = new Pagger() { PageIndex = 1, PageSize = 1, Total = -1 };
            DataTable dt = DoQuery(param);
            foreach (DataRow dr in dt.Rows)
            {
                T t = System.Activator.CreateInstance(typeof(T), false) as T;
                t.ParseFromTableRow(dr);
                return t;
            }
            return null;
        }

        /// <summary>
        /// 返回前几条
        /// </summary>
        /// <param name="top">前多少条</param>
        /// <param name="where">查询条件（动态类）</param>
        /// <param name="permission">配置项名称</param>
        /// <param name="queryFilter">查询列（实体属性）过滤，以逗号隔开</param>
        public List<T> QueryTopMany<T>(int top, object where, bool? strictModel = null, string permission = null, string queryFilter = null, string orderBy = null) where T : IDBEntity
        {
            QueryParam param = new QueryParam() { queryField = queryFilter, entityType = typeof(T), permission = permission, StrictModel = strictModel };
            if (where != null) param.SetWhere(where);
            if (orderBy != null) param.orderBy = orderBy;
            param.Page = new Pagger() { PageIndex = 1, PageSize = top, Total = -1 };
            return QueryMany<T>(param);
        }

        /// <summary>
        /// 查询表内容，返回树弄列表
        /// </summary>                
        /// <param name="parentVal">父节点的值，空则查询全部</param>
        /// <returns></returns>
        public List<T> QueryTree<T>(string permission, object where, string orderBy, object parentVal = null, bool? strictModel = null) where T : ITreeDBEntity
        {

            QueryParam param = new QueryParam() { StrictModel = strictModel, permission = permission, queryField = "*", entityType = typeof(T), orderBy = orderBy };
            if (where != null) param.SetWhere(where);
            return QueryTree<T>(param, parentVal);
        }

        /// <summary>
        /// 查询表内容，返回树弄列表
        /// </summary>                
        /// <param name="parentVal">根节点的值或者sql表达式，不传则取parent is null or parent = 0， sql表达式需要包含${parent} </param>
        /// <returns></returns>
        public List<T> QueryTree<T>(QueryParam param, object parentVal = null) where T : ITreeDBEntity
        {
            if (param.entityType == null) param.entityType = typeof(T);
            CustomerProperty cp = param.LoaderInfo.GetParentCustomerProperty();
            if (string.IsNullOrEmpty(cp.Attr.ForeignProperty)) throw new ClientException(cp.Info.Name + "没有定义ForeignTableField");
            string parentField = cp.Info.Name;//.GetDBFieldName(null);
            if (param.ClientWhere != null && param.ClientWhere.ContainsKey(parentField)) throw new ClientException("查询条件中不能包含" + parentField);
            DataTable dtAll = DoQuery(param);
            string filterExp = null;
            DataRow[] rootRows = null;
            if (parentVal == null)
            {
                //查找一级节点（parent列没有对应的id的）
                List<DataRow> dataRowList = new List<DataRow>();
                HashSet<object> allIDs = new HashSet<object>(dtAll.AsEnumerable().Select(row => row[cp.Attr.ForeignProperty]));//ForeignProperty 就是id
                foreach (DataRow row in dtAll.Rows)
                {
                    parentVal = row[parentField];
                    if (parentVal == DBNull.Value || parentVal.Equals("0") || !allIDs.Contains(parentVal))
                    {
                        dataRowList.Add(row);
                    }
                }
                rootRows = dataRowList.ToArray();
            }
            else if (parentVal.Equals("0") || parentVal.ToString().Equals("0"))
            {
                filterExp = "(" + parentField + " is null or " + parentField + "= '0' )";
            }
            else
            {
                string parentValString = parentVal.ToString();

                var hasBlank = parentValString.IndexOf(' ');
                if (hasBlank > 0)
                {
                    //sql 语句
                    filterExp = parentValString.Replace("${parent}", parentField);

                }
                else
                {
                    filterExp = parentField + "='" + parentValString + "'";

                }
            }
            if (filterExp != null && rootRows == null) rootRows = dtAll.Select(filterExp);
            List<T> lst = new List<T>();

            foreach (DataRow dr in rootRows)
            {
                T entity = (T)System.Activator.CreateInstance(param.entityType, false);
                entity.ParseFromTableRow(dr);
                lst.Add(entity);
            }
            var queryInstance = (QueryEntityInstance)Thread.GetData(Thread.GetNamedDataSlot("queryInstance"));
            foreach (T sub in lst)
            {
                SetTreeChildren(queryInstance, sub, cp, dtAll);
            }
            return lst;
        }
        /// <summary>
        /// 查询表内容，返回树弄列表
        /// </summary>        
        /// <param name="parentVal">父节点的值，空则查询全部</param>
        /// <returns></returns>
        public List<ITreeDBEntity> QueryTree(QueryParam param, object parentVal = null)
        {
            return QueryTree<ITreeDBEntity>(param, parentVal);
        }

        //查询treeEntity子级树 cp为parent键
        private void SetTreeChildren(QueryEntityInstance queryInstance, ITreeDBEntity treeEntity, CustomerProperty cp, DataTable dtAll)
        {
            if (treeEntity == null) throw new ClientException(treeEntity.GetType().Name + "不是ITreeDBEntity类型，或者查询数据转换为空");
            //treeEntity主键，对过cp的ForeignProperty反查
            CustomerProperty primaryCodeCP = queryInstance.Param.LoaderInfo.GetCustomerProperty(cp.Attr.ForeignProperty);
            if (primaryCodeCP == null) throw new Exception(cp.Info.Name + "外键对应的主键" + cp.Attr.ForeignProperty + "找不到");
            //treeEntity主键值
            object primaryCode = primaryCodeCP.Info.GetValue(treeEntity, null);

            //queryInstance.Param.ClientWhere[cp.GetDBFieldName()] = primaryCode.ToString();
            //过滤datatable
            string filterExp = cp.Info.Name + "='" + primaryCode + "'";
            ITreeDBEntity.TreeDBEntityCollection lst = new ITreeDBEntity.TreeDBEntityCollection(treeEntity);
            DataRow[] rootRows = dtAll.Select(filterExp);
            foreach (DataRow dr in rootRows)
            {
                ITreeDBEntity subEntity = (ITreeDBEntity)System.Activator.CreateInstance(queryInstance.Param.entityType, false);
                subEntity.ParseFromTableRow(dr);
                treeEntity.Children.Add(subEntity);
                //subEntity.Parent = treeEntity;
                lst.Add(subEntity);
            }
            if (lst.Count > 0)
            {
                treeEntity.Children = lst;
                foreach (ITreeDBEntity sub in treeEntity.Children)
                {
                    SetTreeChildren(queryInstance, sub, cp, dtAll);
                }
            }
        }
        /// <summary>
        /// 查询是否有指定的记录
        /// </summary>
        /// <param name="permission">查询配置项</param>
        /// <param name="entityName">实体名</param>
        /// <param name="where">条件动态类</param>
        /// <returns></returns>
        public bool Exists(string permission, string entityName, object where)
        {
            // string whereJson = Newtonsoft.Json.JsonConvert.SerializeObject(where);
            QueryParam param = new QueryParam() { entityName = GetFullName(entityName), permission = permission, queryField = "count(0)" };
            if (where != null) param.SetWhere(where);
            DataTable dt = DoQuery(param);
            if (dt.Rows[0][0] == DBNull.Value) return false;
            return Convert.ToInt32(dt.Rows[0][0]) > 0;
        }

        /// <summary>
        /// 查询是否有指定的记录
        /// </summary>                
        /// <param name="where">条件动态类</param>
        /// <returns></returns>
        public bool Exists<T>(object where) where T : IDBEntity
        {
            QueryParam param = new QueryParam() { entityType = typeof(T), permission = null, queryField = "count(0)" };
            if (where != null) param.SetWhere(where);
            var queryInstance = SetQueryEntityConfig(param);
            string sql;
            IDbDataParameter[] parameters;
            ParseQuerySql(queryInstance, out sql, out parameters);
            var scalarObj = GetDBAccess().ExecScalar(sql, CommandType.Text, parameters);
            if (scalarObj == null || scalarObj == DBNull.Value) return false;
            return Convert.ToInt64(scalarObj) > 0;
        }

        /// <summary>
        /// 查询记录数
        /// </summary>        
        /// <param name="entityName"></param>
        /// <param name="where">条件动态类</param>
        /// <returns></returns>
        public int Count<T>(object where) where T : IDBEntity
        {
            // QueryParam param = new QueryParam() { entityType = typeof(T), queryField = "count(0) cc" };
            // if (where != null) param.SetWhere(where);
            object obj = ExecScalar<T>("count(0) cc", where, null);
            if (obj != null && obj != DBNull.Value) return Convert.ToInt32(obj);
            return 0;
            // DataTable dt = DoQuery(param);
            // if (dt.Rows[0][0] == DBNull.Value) throw new ClientException("查询" + typeof(T).Name + "的Count异常");
            // return Convert.ToInt32(dt.Rows[0][0]);
        }

        /// <summary>
        /// 查询记录数
        /// </summary>        
        /// <param name="entityName"></param>
        /// <param name="where">条件动态类</param>
        /// <returns></returns>
        public Int64 MaxPrimary<T>(object where = null) where T : IDBEntity
        {
            Type entityType = typeof(T);
            QueryParam param = new QueryParam() { entityType = entityType };
            if (where != null) param.SetWhere(where);
            string primaryKey = param.LoaderInfo.PrimaryCusPro.GetDBFieldName(null);
            param.queryField = "Max(" + primaryKey + ")";
            var queryInstance = SetQueryEntityConfig(param);
            string sql;
            IDbDataParameter[] parameters;
            ParseQuerySql(queryInstance, out sql, out parameters);
            object scalar = GetDBAccess().ExecScalar(sql, CommandType.Text, parameters);
            if (scalar == null) return 0;
            else return Convert.ToInt64(scalar);
        }

        /// <summary>
        /// 获取表主键的下一个序号
        /// </summary>
        public Int64 Sequence<T>() where T : IDBEntity
        {
            Type entityType = typeof(T);
            if (DBContext.UserRedis)
            {
                DBTableAttribute tableAttr = GetTableAttr(entityType);
                //如果使用redis缓存 ，则使得缓存来实现自增
                string key = tableAttr.TableName + "_identity";
                Int64 identity = GetRedisDatabase(DBIdentity_Redis_Database_Index).IncrementRedisItem(key);
                if (identity < 2)
                {
                    identity = MaxPrimary<T>();
                    if (identity == 0) identity = 1;
                    identity++;
                    GetRedisDatabase(DBIdentity_Redis_Database_Index).SetRedisItem(key, identity.ToString(), DateTime.Now.AddDays(1));
                    //SetRedisItem(key, identity.ToString(), DateTime.Now.AddDays(1));
                }
                //idetity++;
                //SetRedisItem(key, idetity); 
                return (Int64)identity;
            }
            else
            {
                return MaxPrimary<T>() + 1;
            }
        }

        /// <summary>
        /// 查询结果返回List
        /// </summary>
        /// <param name="where">查询条件（动态类）</param>
        /// <param name="queryFilter">查询列（实体属性）过滤，以逗号隔开</param>
        /// <returns></returns>
        public List<T> QueryMany<T>(object where, string queryFilter = null) where T : IDBEntity
        {
            return QueryMany<T>(where, null, queryFilter, null);
        }


        /// <summary>
        /// 通用查询列表,多表关联以及条件表达式请在json文件中配置
        /// </summary>
        /// <param name="param">查询参数（permission:权限和表达式配置,queryField:查询的字段，客户端实体的名称，逗号隔开,entityType:查询的对象,whereField：查询条件json，比如{aa:'1',dtime:'1,2'} ）</param>        
        public List<T> QueryMany<T>(QueryParam param) where T : IDBEntity
        {
            List<T> lst = new List<T>();
            param.entityType = typeof(T);
            DataTable dt = DoQuery(param);
            foreach (DataRow dr in dt.Rows)
            {
                T t = System.Activator.CreateInstance(typeof(T), false) as T;
                t.ParseFromTableRow(dr);
                lst.Add(t);
            }

            return lst;
        }

        /// <summary>
        /// 查询结果返回List
        /// </summary>
        /// <param name="where">查询条件（动态类）</param>
        /// <param name="permission">配置项名称</param>
        /// <param name="queryFilter">查询列（实体属性）过滤，以逗号隔开</param>
        public List<T> QueryMany<T>(object where, string permission, string queryFilter, string orderBy = null, bool? strictModel = null) where T : IDBEntity
        {

            stepMsg = "解析where json";
            QueryParam param = new QueryParam() { StrictModel = strictModel, queryField = queryFilter, orderBy = orderBy, entityType = typeof(T), permission = permission };
            if (where != null) param.SetWhere(where);
            return QueryMany<T>(param);
        }

        //private string[] GetTables(QueryEntityConfig qEntity)
        //{

        //    string strTables = qEntity.TableSql;
        //    int pos = strTables.IndexOf("join");
        //    ArrayList arrlist = new ArrayList();
        //    while (pos > -1)
        //    {
        //        strTables = strTables.Substring(pos + 5);
        //        string tableName;
        //        int pos2 = strTables.IndexOf(' ');
        //        if (pos2 == -1) tableName = strTables;
        //        else tableName = strTables.Substring(0, pos2);
        //        arrlist.Add(tableName);
        //        pos = strTables.IndexOf("join");
        //    }
        //    return arrlist.ToArray(typeof(string)) as string[];
        //}

        //解析生成语句，根据query设定，是否执行返回datatable
        public DataTable ParseQueryTable(QueryEntityInstance queryInstance)
        {
            string sql;
            IDbDataParameter[] parameters;
            ParseQuerySql(queryInstance, out sql, out parameters);
            return GetDBAccess().QueryTable(sql, CommandType.Text, parameters);
        }

        /// <summary>
        /// 不执行查询，返回sql数组和参数
        /// </summary>
        public string[] ParseQuerySql(QueryParam param, out IDbDataParameter[] dbDataParameter)
        {
            var queryInstance = SetQueryEntityConfig(param);
            string[] sqlArray;
            ParseQuerySql(queryInstance, out sqlArray, out dbDataParameter);
            return sqlArray;
        }

        /// <summary>
        /// 不执行查询，返回sql和参数
        /// </summary>
        public void ParseQuerySql(QueryEntityInstance queryInstance, out string sql, out IDbDataParameter[] parameters)
        {
            string[] sqlArray;
            ParseQuerySql(queryInstance, out sqlArray, out parameters);
            if (queryInstance.Param.Page != null && sqlArray.Length > 1)
            {
                using (IDataReader dr = GetDBAccess().QueryReader(sqlArray[0], CommandType.Text, parameters))
                {
                    if (dr.Read())
                    {
                        queryInstance.Param.Page.Total = Convert.ToInt32(dr[0]);
                        if(queryInstance.Param.Page.GroupByDic!=null){
                            for (int i = 1; i < dr.FieldCount; i++)
                            {
                                string name = dr.GetName(i);
                                queryInstance.Param.Page.GroupByDic[name] = dr.GetValue(i);
                            }
                        }
                        dr.Close();
                    }
                    else throw new Exception("分页查询total结果返回为空");
                }
            }
            sql = sqlArray[sqlArray.Length - 1];
        }

        public void ParseQuerySql(QueryEntityInstance queryInstance, out string[] sql, out IDbDataParameter[] parameters)
        {
            if (queryInstance.Config.NotAllowQuery.Length > 0 && queryInstance.Config.NotAllowQuery[0] == "*") throw new ClientException("不允许查询");
            stepMsg = "进入解析查询";
            DBTableAttribute tableAttr = GetTableAttr(queryInstance.Param.entityType);
            string fromTableSql;
            if (queryInstance.Config.TableSql == null) fromTableSql = tableAttr.TableName;
            else fromTableSql = FormatFromSource(queryInstance.Config.TableSql);


            stepMsg = "组织where的语句";
            string WhereSql = queryInstance.Param.GenWhereSql(queryInstance, tableAttr, out parameters);
            stepMsg = "组织selete前面的语句";
            StringBuilder sb = new StringBuilder();
            foreach (QueryField qf in queryInstance.Param.QueryFields)
            {
                string dbFileName = GetQueryField(queryInstance, qf, 0, tableAttr);
                if (dbFileName == null) continue;
                sb.Append(",");
                sb.Append(dbFileName);
            }
            string QueryFieldSql = FormatFromSource(sb.ToString().Substring(1));
            //order by
            if (queryInstance.Param.OrderFields == null || queryInstance.Param.OrderFields.Count == 0)
            {
                //没有orderby 如果需要分页，则使用主键
                if (queryInstance.Param.Page != null)
                {
                    queryInstance.Param.orderBy = GetDbField(queryInstance, queryInstance.Param.LoaderInfo.PrimaryCusPro, 2, tableAttr);
                }
            }
            else
            {
                //有传orderby
                queryInstance.Param.orderBy = "";
                foreach (OrderField qf in queryInstance.Param.OrderFields)
                {
                    string dbFileName = GetQueryField(queryInstance, qf, 2, tableAttr);
                    if (dbFileName == null) continue;
                    if (dbFileName.IndexOf('(') > -1) LogMessage("最好不要使用" + dbFileName + "来排序，请配置排序规则！", "ParseQuery");
                    queryInstance.Param.orderBy += "," + dbFileName;
                    if (qf.Orientation != null) queryInstance.Param.orderBy += " " + qf.Orientation;
                }
                queryInstance.Param.orderBy = queryInstance.Param.orderBy.Substring(1);
            }
            stepMsg = "执行查询语句";
            if (queryInstance.Param.Page != null)
            {

                int startIndex = (queryInstance.Param.Page.PageIndex - 1) * queryInstance.Param.Page.PageSize + 1;
                int endIndex = startIndex + queryInstance.Param.Page.PageSize - 1;
                if ((this.GetConfig().AlwayQueryCount || queryInstance.Param.Page.PageIndex == 1) && queryInstance.Param.Page.Total != -1) //始终查询，或者只在第一页查询count，Total == -1用来做top查询
                {
                    sql = new string[2];
                    sql[0] = queryPagingCount(queryInstance, parameters, ref fromTableSql, ref WhereSql);
                }
                else sql = new string[1];
                stepMsg = "执行分页查询";
                // var newParameters = new IDbDataParameter[parameters.Length + 2];
                // for (int i = 0; i < parameters.Length; i++) newParameters[i] = parameters[i];
                // IDbDataParameter pageIndexParameter, pageSizeParameter;
                // newParameters[newParameters.Length - 2] = pageIndexParameter = GetDBAccess().CreateParameter("pageIndex", queryInstance.Param.Page.PageIndex);
                // newParameters[newParameters.Length - 1] = pageSizeParameter = GetDBAccess().CreateParameter("pageSize", queryInstance.Param.Page.PageSize);
                // parameters = newParameters;
                sql[sql.Length - 1] = GetDBAccess().PartQuerySql(QueryFieldSql, fromTableSql, WhereSql, queryInstance.Param.orderBy, startIndex, endIndex);

            }
            else
            {
                sql = new string[1];
                string sqlTemp = "select " + QueryFieldSql + " from " + fromTableSql;
                if (!string.IsNullOrEmpty(WhereSql))
                {
                    sqlTemp += " where " + WhereSql;
                }
                if (!string.IsNullOrEmpty(queryInstance.Param.orderBy)) sqlTemp += " order by " + queryInstance.Param.orderBy;
                sql[sql.Length - 1] = sqlTemp;

            }
        }



        public QueryParam CreateQueryBuilder()
        {
            return QueryParam.CreateFromContext(this);
        }


        // private string GenWhereSql(QueryEntityInstance queryInstance, DBTableAttribute tableAttr, StringBuilder sb, out IDbDataParameter[] parameters)
        // {
        //     string WhereSql = "";
        //     stepMsg = "组织where的语句";
        //     //如果有group by 放在最后
        //     string groupby = "";
        //     Type entityType = queryInstance.Param.entityType;
        //     List<IDbDataParameter> parameterList = new List<IDbDataParameter>();
        //     foreach (KeyValuePair<string, IWhereItem> ki in queryInstance.Param.ClientWhere)
        //     {
        //         stepMsg = "解析" + ki.Key;
        //         IDbDataParameter[] itemParameters;
        //         var strItem = queryInstance.CreateWhereItemParameters(ki.Key,ki.Value,this,out itemParameters);
        //         if (itemParameters != null) parameterList.AddRange(itemParameters);
        //         if (ki.Value is WhereItem_GroupBy || ((ki.Value is WhereItem_Custom) && ((WhereItem_Custom)ki.Value).IsGroupBy))
        //         {
        //             groupby = strItem;
        //         }
        //         else
        //         {
        //             sb.Append(" and (" + strItem + ")");
        //         }
        //     }
        //     // if (sb.Length > 0) WhereSql = FormatFromSource(sb.ToString().Substring(5));
        //     if (sb.Length > 0) WhereSql = sb.ToString().Substring(5);
        //     if (groupby.Length > 0)
        //     {
        //         if (WhereSql.Length > 1)
        //         {
        //             WhereSql += " " + groupby.Replace("1=1", "");
        //         }
        //         else
        //         {
        //             //没有其它条件，后面会拼where所以要加1=1
        //             WhereSql += " 1=1 " + groupby.Replace("1=1", ""); ;
        //         }
        //     }
        //     sb.Clear();
        //     parameters = parameterList.ToArray();
        //     return WhereSql;
        // }


        private string queryPagingCount(QueryEntityInstance queryInstance, IDbDataParameter[] parameters, ref string fromTableSql, ref string WhereSql)
        {
            string gropubyFiledStr = "";
            stepMsg = "分页查询count";
            string queryTotalSql = "select count(0) cc";
            if (queryInstance.Param.Page.GroupByDic != null)
            {
                foreach (string key in queryInstance.Param.Page.GroupByDic.Keys)
                {

                    string[] configArr;
                    queryInstance.Config.Fields.TryGetValue(key, out configArr); //查找查询条件表达式的配置
                    if (configArr == null) throw new ClientException("在分页查询中使用额外的汇总字段" + key + "，需要在Permission中定义Fields");
                    string groupFieldFunc = "," + configArr[0] + " " + key;
                    queryTotalSql += groupFieldFunc;
                    gropubyFiledStr += groupFieldFunc;
                }
            }
            queryTotalSql += " from " + fromTableSql;
            if (!string.IsNullOrEmpty(WhereSql))
            {
                queryTotalSql += " where " + WhereSql;
            }
            if (WhereSql.IndexOf("group by", StringComparison.OrdinalIgnoreCase) > 1)
            {
                // group by 日前利用where里面配置的技巧来实现，在count的时候会不太对，需要处理
                //取出字段
                var rex = new Regex(@"\((.*)\)");
                var groupFieldInner = "";
                int i = 0;
                foreach (string gropubyFiledStrItem in gropubyFiledStr.Split(','))
                {
                    if (gropubyFiledStrItem.Length < 3) continue;
                    foreach (System.Text.RegularExpressions.Match math in rex.Matches(gropubyFiledStrItem))
                    {
                        i++;
                        if (math.Groups.Count > 0)
                        {
                            string mathField = math.Groups[1].Value;
                            string[] configArr;

                            gropubyFiledStr = gropubyFiledStr.Replace("(" + mathField + ")", "(gf_" + i + ")");
                            while (queryInstance.Config.Fields.TryGetValue(mathField, out configArr) && configArr.Length != 0)
                            {
                                mathField = configArr[0];
                            }
                            groupFieldInner += "," + mathField + " as gf_" + i;
                        }
                    }
                }
                if (groupFieldInner.Length > 0) groupFieldInner = groupFieldInner.Substring(1);
                else groupFieldInner = "1 as count";
                queryTotalSql = "select count(0) Count " + gropubyFiledStr + " from (select " + groupFieldInner + "  from " + fromTableSql;
                if (!string.IsNullOrEmpty(WhereSql)) queryTotalSql += " where " + WhereSql;
                queryTotalSql += ") t";
            }
            return queryTotalSql;

        }

        /// <summary>
        /// 保存新对象到表(Insert)，可以配置文件中设定不允许修改的列NotAllow
        /// </summary>
        /// <param name="permission">保存配置项</param>
        /// <param name="entity">要保存的实体对象</param>
        /// <param name="columns">过滤仅要保存的属性</param>
        public int DoSaveNew(IDBEntity entity, string permission = null, string columns = null, bool? strictModel = null)
        {
            var queryInstance = SetQueryEntityConfig(new QueryParam() { StrictModel = strictModel, permission = permission, entityType = entity.GetType() });
            string[] filters = null;
            if (columns != null) filters = columns.Split(',');
            int result = SaveNewEntity(queryInstance, entity, null, filters);
            return result;
        }

        /// <summary>
        /// 批量保存（插入）对象到表，根据主键是否有值来判断是插入还是更新，可以配置文件中设定不允许修改的列NotAllow
        /// </summary>
        /// <param name="entityList">实体集合</param>
        /// <param name="permission">保存配置项</param>
        /// <param name="entity">要保存的实体对象</param>
        /// <param name="columns">过滤仅要保存的属性</param>
        public void DoBulkInsert(IEnumerable<IDBEntity> entityList, string permission = null, string columns = null, bool? strictModel = null)
        {
            if (entityList.Count() == 0) return;
            var firstObject = entityList.First<IDBEntity>();
            SetQueryEntityConfig(new QueryParam() { StrictModel = strictModel, permission = permission, entityType = firstObject.GetType() });
            DataTable dtInsert = new DataTable();
            Type entityType = firstObject.GetType();
            EntityLoaderInfo loaderInfo = EntityLoaderInfo.GetEntityLoaderInfo(entityType);
            //if (queryInstance.Param.StrictModel.Value && queryInstance.Config.NotAllowSaving.Length > 0 && queryInstance.Config.NotAllowSaving[0] == "*") throw new ClientException("当前的配置不允许对" + entityType.Name + "进行更改操作！");
            EntityInstanceParseInfo parseInfo = ParseCustomerAttr(entityType, firstObject);
            string primarkeyFieldName = parseInfo.primaryCusPro.GetDBFieldName(null);
            stepMsg = "开始批量保存" + entityType.Name;
            if (string.IsNullOrEmpty(parseInfo.primaryKey) || parseInfo.primaryCusPro == null) throw new ClientException(firstObject.GetType().Name + "的DBTableAttribute属性没有定义主键");
            //如果有标记删除的列，并且没有值的，比如Status，赋值1
            if (loaderInfo.MarkDeleteCusPro != null)
            {
                foreach (var obj in entityList)
                {
                    CustomerProperty markDelCus = loaderInfo.MarkDeleteCusPro;
                    Object o = markDelCus.Info.GetValue(obj, null);
                    if (o == null || o.Equals(IDBEntity.DefaultNullValue))
                    {
                        markDelCus.Info.SetValue(obj, markDelCus.Attr.MarkDeleteValue[0], null);
                        if (!parseInfo.proListExcludePrimary.ContainsKey(markDelCus.Info.Name))
                        {
                            parseInfo.proListExcludePrimary.Add(markDelCus.Info.Name, new EntityInstanceParseInfo.ValueCustomerProperty() { CusProperty = markDelCus, PropertyValue = markDelCus.Attr.MarkDeleteValue[0] });
                        }
                    }
                }
            }
            //初始化datatable行
            foreach (var obj in entityList)
            {
                var dr = dtInsert.NewRow();
                dtInsert.Rows.Add(dr);
            }
            var filterPropertys = parseInfo.proListExcludePrimary;
            if (filterPropertys.Count == 0) throw new Exception("没有可保存的列");

            stepMsg = "组织datatable";

            var customIncream = !GetDBAccess().AotoIdentity || !parseInfo.primaryCusPro.Attr.Identity;
            //如果不支持自动增长，或者主键没显示定义自动增长
            int rowIndex = 0;
            if (customIncream)
            {
                dtInsert.Columns.Add(primarkeyFieldName, parseInfo.primaryCusPro.Info.PropertyType);
                foreach (var obj in entityList)
                {
                    object pkValue = parseInfo.primaryCusPro.Info.GetValue(obj);
                    if (pkValue == null || pkValue.ToString() == "0")
                    {
                        //主键没有赋值，则使用redis自增
                        object idetity = GetIdentityValue(parseInfo.tableAttr.TableName, parseInfo.primaryKey);
                        parseInfo.primaryKeyVal = pkValue = Convert.ChangeType(idetity, parseInfo.primaryCusPro.Info.PropertyType);
                        parseInfo.primaryCusPro.Info.SetValue(obj, pkValue, null);
                    }
                    dtInsert.Rows[rowIndex][primarkeyFieldName] = pkValue;
                    rowIndex++;
                }

            }
            foreach (KeyValuePair<string, EntityInstanceParseInfo.ValueCustomerProperty> kv in filterPropertys)
            {
                string columnName = kv.Value.CusProperty.GetDBFieldName(entityList.First());
                if (Nullable.GetUnderlyingType(kv.Value.CusProperty.Info.PropertyType) != null)
                {
                    //可空类型
                    dtInsert.Columns.Add(columnName, kv.Value.CusProperty.Info.PropertyType.GetGenericArguments()[0]);
                }
                else if (kv.Value.CusProperty.Info.PropertyType == typeof(object))
                {
                    //object类型，从行数据里面查找真实的类型
                    bool hasVal = false;
                    foreach (var obj in entityList)
                    {
                        var columnRowValue = kv.Value.CusProperty.Info.GetValue(obj);
                        if (columnRowValue != null)
                        {
                            dtInsert.Columns.Add(columnName, columnRowValue.GetType());
                            hasVal = true;
                            break;
                        }
                    }
                    //该列全部没有数据的，直接用string
                    if (!hasVal) dtInsert.Columns.Add(columnName, typeof(string));
                }
                else dtInsert.Columns.Add(columnName, kv.Value.CusProperty.Info.PropertyType);
                rowIndex = 0;
                foreach (var obj in entityList)
                {
                    dtInsert.Rows[rowIndex][columnName] = kv.Value.CusProperty.Info.GetValue(obj);
                    rowIndex++;
                }
            }
            stepMsg = "执行批量保存";
            GetDBAccess().BulkInsert(parseInfo.tableAttr.TableName, dtInsert);

        }

        /// <summary>
        /// 批量更新对象到表，根据主键是否有值来判断是插入还是更新，可以配置文件中设定不允许修改的列NotAllow
        /// </summary>
        /// <param name="entityList">实体集合</param>
        /// <param name="permission">保存配置项</param>
        /// <param name="entity">要保存的实体对象</param>
        /// <param name="columns">过滤仅要保存的属性</param>
        public void DoBulkUpdate(IEnumerable<IDBEntity> entityList, string columns = null)
        {
            if (entityList.Count() == 0) return;
            var firstObject = entityList.First<IDBEntity>();
            SetQueryEntityConfig(new QueryParam() { entityType = firstObject.GetType() });
            DataTable dtUpdate = new DataTable();
            Type entityType = firstObject.GetType();
            EntityLoaderInfo loaderInfo = EntityLoaderInfo.GetEntityLoaderInfo(entityType);
            //if (queryInstance.Param.StrictModel.Value && queryInstance.Config.NotAllowSaving.Length > 0 && queryInstance.Config.NotAllowSaving[0] == "*") throw new ClientException("当前的配置不允许对" + entityType.Name + "进行更改操作！");
            EntityInstanceParseInfo parseInfo = ParseCustomerAttr(entityType, firstObject);
            stepMsg = "开始批量保存" + entityType.Name;
            if (string.IsNullOrEmpty(parseInfo.primaryKey) || parseInfo.primaryCusPro == null) throw new ClientException(firstObject.GetType().Name + "的DBTableAttribute属性没有定义主键");
            string primarkeyFieldName = parseInfo.primaryCusPro.GetDBFieldName(null);

            //如果有标记删除的列，并且没有值的，比如Status，赋值1
            if (loaderInfo.MarkDeleteCusPro != null)
            {
                foreach (var obj in entityList)
                {
                    CustomerProperty markDelCus = loaderInfo.MarkDeleteCusPro;
                    Object o = markDelCus.Info.GetValue(obj, null);
                    if (o == null || o.Equals(IDBEntity.DefaultNullValue))
                    {
                        markDelCus.Info.SetValue(obj, markDelCus.Attr.MarkDeleteValue[0], null);
                        if (!parseInfo.proListExcludePrimary.ContainsKey(markDelCus.Info.Name))
                        {
                            parseInfo.proListExcludePrimary.Add(markDelCus.Info.Name, new EntityInstanceParseInfo.ValueCustomerProperty() { CusProperty = markDelCus, PropertyValue = markDelCus.Attr.MarkDeleteValue[0] });
                        }
                    }
                }
            }
            //初始化datatable行
            foreach (var obj in entityList)
            {
                var dr = dtUpdate.NewRow();
                dtUpdate.Rows.Add(dr);
            }
            Dictionary<string, EntityInstanceParseInfo.ValueCustomerProperty> filterPropertys;
            if (columns != null)
            {
                filterPropertys = new Dictionary<string, EntityInstanceParseInfo.ValueCustomerProperty>();
                foreach (string column in columns.Split(','))
                {
                    EntityInstanceParseInfo.ValueCustomerProperty vcp;
                    if (!parseInfo.proListExcludePrimary.TryGetValue(column, out vcp)) throw new Exception("找不到列" + column);
                    filterPropertys.Add(column, vcp);
                }
            }
            else
            {
                filterPropertys = parseInfo.proListExcludePrimary;
            }
            if (filterPropertys.Count == 0) throw new Exception("没有可保存的列");

            stepMsg = "组织datatable";

            var customIncream = !GetDBAccess().AotoIdentity || !parseInfo.primaryCusPro.Attr.Identity;
            //如果不支持自动增长，或者主键没显示定义自动增长
            int rowIndex = 0;
            dtUpdate.Columns.Add(primarkeyFieldName, parseInfo.primaryCusPro.Info.PropertyType);
            foreach (var obj in entityList)
            {
                dtUpdate.Rows[rowIndex][primarkeyFieldName] = parseInfo.primaryCusPro.Info.GetValue(obj);
                rowIndex++;
            }


            // if (queryInstance.Param.StrictModel.Value )
            // {
            //     foreach (string str in queryInstance.Config.NotAllowSaving)
            //     {
            //         if (filterPropertys.ContainsKey(str)) throw new ClientException("当前的Permission配置，不允许修改" + str + "列的值");
            //     }
            // }
            foreach (KeyValuePair<string, EntityInstanceParseInfo.ValueCustomerProperty> kv in filterPropertys)
            {
                string columnName = kv.Value.CusProperty.GetDBFieldName(null);
                dtUpdate.Columns.Add(columnName, kv.Value.CusProperty.Info.PropertyType);
                rowIndex = 0;
                foreach (var obj in entityList)
                {
                    dtUpdate.Rows[rowIndex][columnName] = kv.Value.CusProperty.Info.GetValue(obj);
                    rowIndex++;
                }
            }
            //创建临时表，先将数据批量插入到临时表，再通过临时表去更新
            var dbAccess = GetDBAccess();
            List<DataColumn> notPrimaryColumnList = new List<DataColumn>();
            DataColumn primaryColumn = null;//DataTable中主键列
            foreach (DataColumn column in dtUpdate.Columns)
            {
                if (column.ColumnName == primarkeyFieldName) primaryColumn = column;
                else notPrimaryColumnList.Add(column);
            }
            stepMsg = "创建临时表";
            DataColumn[] notPrimaryArray = notPrimaryColumnList.ToArray();//DataTable中不包含主键的列
            if (primaryColumn != null) notPrimaryColumnList.Add(primaryColumn);
            DataColumn[] allColumnArray = notPrimaryColumnList.ToArray();//DataTable中所有的列
            string tempTableFullName = dbAccess.CreateTempTable("TmpTable_" + parseInfo.tableAttr.TableName, allColumnArray, primaryColumn);
            try
            {
                stepMsg = "执行批量保存到临时表" + tempTableFullName;
                dbAccess.BulkInsert(tempTableFullName, dtUpdate);
                stepMsg = "更新" + parseInfo.tableAttr.TableName + "表";
                dbAccess.UpdateByTempTable(parseInfo.tableAttr.TableName, tempTableFullName, notPrimaryArray, primaryColumn);
            }
            finally
            {
                dbAccess.DropTempTable(tempTableFullName);
            }

        }



        /// <summary>
        /// 保存对象到表，根据主键是否有值来判断是插入还是更新，可以配置文件中设定不允许修改的列NotAllow
        /// </summary>
        /// <param name="permission">保存配置项</param>
        /// <param name="entity">要保存的实体对象</param>
        /// <param name="columns">过滤仅要保存的属性</param>
        public int DoSave(IDBEntity entity, string permission = null, string columns = null, bool? strictModel = null)
        {
            var queryInstance = SetQueryEntityConfig(new QueryParam() { StrictModel = strictModel, permission = permission, entityType = entity.GetType() });
            string[] filters = null;
            int result = SaveEntity(queryInstance, entity, null, filters);

            return result;
        }

        /// <summary>
        /// 保存对象对表，可以配置文件中设定不允许修改的列NotAllow
        /// </summary>
        /// <param name="permission">权限和表达式配置</param>
        /// <param name="entityType">类型</param>
        /// <param name="entityJson">对象json</param>
        /// <returns></returns>
        public IDBEntity DoSave(string permission, string entityName, string entityJson)
        {
            var queryInstance = SetQueryEntityConfig(new QueryParam() { entityName = GetFullName(entityName), permission = permission });
            if (!queryInstance.Param.entityType.IsSubclassOf(typeof(IDBEntity))) throw new ClientException(queryInstance.Param.entityType.Name + "类型没有继承IDBEntity");
            stepMsg = "解析保存对象json";
            IDBEntity main = Newtonsoft.Json.JsonConvert.DeserializeObject(entityJson, queryInstance.Param.entityType, new Newtonsoft.Json.JsonSerializerSettings()) as IDBEntity;
            if (main == null) throw new ClientException("json序列化为对象异常，结果为空，可能类型不对");
            SaveEntity(queryInstance, main, null);

            return main as IDBEntity;
        }

        /// <summary>
        /// 更新单个列
        /// </summary>        
        /// <param name="PropertyName">实体属性</param>
        /// <param name="value">值</param>
        /// <returns>受影响行数</returns>
        public int Update<T>(string PropertyName, object value, int primaryKey) where T : IDBEntity
        {
            T t = System.Activator.CreateInstance(typeof(T), false) as T;
            t.SetPrimaryValue(primaryKey);
            var queryInstance = SetQueryEntityConfig(new QueryParam() { permission = null, entityType = typeof(T) });
            t.SetPropertyValue(PropertyName, value);
            return SaveEntity(queryInstance, t, null);
        }

        /// <summary>
        /// 更新单个列
        /// </summary>        
        /// <param name="columnAndValues">要更新的内容，动态类，比如{Name="吕存库",Sex=1}</param>
        /// <param name="primaryKey">主键值</param>
        /// <returns>受影响行数</returns>
        public int Update<T>(object columnAndValues, int primaryKey) where T : IDBEntity
        {
            T t = System.Activator.CreateInstance(typeof(T), false) as T;
            t.SetPrimaryValue(primaryKey);
            var queryInstance = SetQueryEntityConfig(new QueryParam() { permission = null, entityType = typeof(T) });
            Dictionary<CustomerProperty, object> filters = new Dictionary<CustomerProperty, object>();
            PropertyInfo[] propertyInfos = columnAndValues.GetType().GetProperties();
            string[] filterColumns = new string[propertyInfos.Length];
            for (int i = 0; i < propertyInfos.Length; i++)
            {
                PropertyInfo info = propertyInfos[i];
                t.SetPropertyValue(info.Name, info.GetValue(columnAndValues, null));
                filterColumns[i] = info.Name;
            }
            return SaveEntity(queryInstance, t, null, filterColumns);
        }

        /// <summary>
        /// 更新单个列
        /// </summary>        
        /// <param name="columnAndValues">要更新的内容字典</param>
        /// <param name="primaryKey">主键值</param>
        /// <returns>受影响行数</returns>
        public int Update<T>(Dictionary<string, object> columnAndValues, int primaryKey) where T : IDBEntity
        {
            T t = System.Activator.CreateInstance(typeof(T), false) as T;
            t.SetPrimaryValue(primaryKey);
            var queryInstance = SetQueryEntityConfig(new QueryParam() { permission = null, entityType = typeof(T) });
            string[] filterColumns = new string[columnAndValues.Count];
            int i = 0;
            foreach (KeyValuePair<string, object> ki in columnAndValues)
            {
                PropertyInfo info = t.GetType().GetProperty(ki.Key);
                if (info == null) throw new ClientException(t.GetType().Name + "中不存在属性" + ki.Key);
                t.SetPropertyValue(info.Name, info.GetValue(columnAndValues, null));
                filterColumns[i] = ki.Key;
                i++;
            }
            return SaveEntity(queryInstance, t, null, filterColumns);
        }

        /// <summary>
        /// 更新实体到数据库
        /// 如果想更新String类型为空，则赋值IDBEntity.DbNullString，int?类型则赋值DefaultNullValue
        /// </summary>
        /// <param name="columns">指定需要更新的属性，逗号隔开，可以为空</param>
        /// <param name="treeParentReplace">树型实体有变更parent的</param>
        /// <returns></returns>
        public int Update(IDBEntity entity, string columns, bool treeParentReplace = false)
        {
            if (entity == null) throw new ArgumentNullException("entity");
            object primary = entity.GetPrimaryValue();
            if (primary == null || primary.ToString().Equals("0") || primary.Equals(IDBEntity.DefaultNullValue)) throw new ClientException("没有设定主键值");
            var queryInstance = SetQueryEntityConfig(new QueryParam() { permission = null, entityType = entity.GetType(), StrictModel = false });
            IDBEntity updated;
            ArrayList filterColumns = new ArrayList();
            if (!string.IsNullOrEmpty(columns))
            {
                updated = System.Activator.CreateInstance(entity.GetType(), false) as IDBEntity;
                updated.SetPrimaryValue(primary);
                string[] arr = columns.Split(',');
                for (int i = 0; i < arr.Length; i++)
                {
                    string field = arr[i];
                    if (filterColumns.Contains(field)) continue;
                    filterColumns.Add(field);
                    PropertyInfo info = updated.GetType().GetProperty(field);
                    if (info == null) throw new ClientException(entity.GetType().Name + "中不存在属性" + field);
                    DBFieldAttribute attribute = info.GetCustomAttribute(typeof(DBFieldAttribute)) as DBFieldAttribute;
                    if (attribute != null && !attribute.IsDBField(this)) continue;
                    var value = info.GetValue(entity, null);
                    info.SetValue(updated, value, null);
                }
            }
            else updated = entity;
            SetArgument("last-update-entity", updated);
            return SaveEntity(queryInstance, updated, null, (string[])filterColumns.ToArray(typeof(string)), treeParentReplace);
        }

        /// <summary>
        /// 客户端提交上来的json数据转为IDBEntity实体
        /// </summary>
        /// <returns></returns>
        public IDBEntity DeserializeEntity(string permission, string entityName, string entityJson)
        {
            //SetQueryEntityConfig();
            entityName = GetFullName(entityName);
            Type entityType = Type.GetType(entityName);
            if (entityType == null) throw new Exception(entityName + "类型找不到!");
            if (!entityType.IsSubclassOf(typeof(IDBEntity))) throw new ClientException(entityType.Name + "类型没有继承IDBEntity");
            stepMsg = "解析保存对象json";
            object main = Newtonsoft.Json.JsonConvert.DeserializeObject(entityJson, entityType, new Newtonsoft.Json.JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
            if (main == null) throw new ClientException("json序列化为对象异常，结果为空，可能类型不对");
            return main as IDBEntity;
        }

        /// <summary>
        /// 获取实体的表定义
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        internal static DBTableAttribute GET_TABLE_ATTR_STATIC(Type t, bool useEntityNameWhenNull = true)
        {
            if (t == null) throw new ClientException("找不到该类型的实体");
            object[] attrs = t.GetCustomAttributes(typeof(DBTableAttribute), true);
            if (attrs.Length < 1)
            {
                return new DBTableAttribute() { TableName = useEntityNameWhenNull ? t.Name : null };
            }
            DBTableAttribute attr = (DBTableAttribute)attrs[0];
            if (attr.TableName == null && useEntityNameWhenNull) attr.TableName = t.Name;
            //throw new ClientException(t.Name + "没有定义DBTableAttribute");
            return attr;
        }

        /// <summary>
        /// 获取属性对应的数据库字段，添加前缀处理
        /// </summary>
        string GetDbField(QueryEntityInstance queryInstance, CustomerProperty cp, DBTableAttribute tableAttr)
        {
            string fileName = cp.GetDBFieldName(null);
            if (tableAttr != null)
            {
                string entityTableAliasName = queryInstance.GetTableAliasName(tableAttr.TableName);
                if (!string.IsNullOrEmpty(entityTableAliasName))
                {
                    //实体定义并且非表里的字段，不加前缀 
                    if (cp.Attr == null || cp.Attr.Usage != DBFieldUsage.NoField)
                    {
                        fileName = entityTableAliasName + "." + fileName;
                    }
                }
            }
            if (cp.Info.PropertyType == typeof(DateTime))
            {
                //是否有定义jsonConvert,日期的处理
                object[] jsonAttrs = cp.Info.GetCustomAttributes(typeof(JsonConverterAttribute), true);
                if (jsonAttrs.Length > 0)
                {
                    Type converterType = ((JsonConverterAttribute)jsonAttrs[0]).ConverterType;
                    if (converterType == typeof(UnixDateConverter))
                    {
                        return string.Format(GetDBAccess().GetDateConverter(10), fileName);
                    }
                    else if (converterType == typeof(UnixTimeConverter))
                    {
                        return string.Format(GetDBAccess().GetDateConverter(19), fileName);
                    }
                }
            }
            //是否要加表前缀
            return fileName;
        }

        /// <summary>
        /// 获取属性对应的数据库字段，如果有配置在Fields则采用配置，否则取属性的定义
        /// </summary>        
        /// <param name="configIndex">配置项索引，0：select  1:where  2: order </param>
        internal string GetDbField(QueryEntityInstance queryInstance, CustomerProperty cp, int configIndex, DBTableAttribute tableAttr)
        {
            if (queryInstance == null) throw new Exception("queryInstance未初始化！");
            string[] configArr;
            queryInstance.Config.Fields.TryGetValue(cp.Info.Name, out configArr);
            if (configArr != null && configArr.Length > 0)
            {
                return configArr.Length > configIndex ? FormatFromSource(configArr[configIndex]) : configArr[0];
            }
            else
            {
                if (tableAttr.IsVirtual)
                {
                    if (cp.Info.DeclaringType != queryInstance.Param.entityType)
                    {
                        //虚拟实体（扩展实体）父类的属性，取父类的字段定义
                        DBTableAttribute declareTableAttre = GetTableAttr(cp.Info.DeclaringType, false);
                        if (declareTableAttre.TableName != null)
                        {
                            return GetDbField(queryInstance, cp, declareTableAttre);
                        }
                        else
                        {
                            return GetDbField(queryInstance, cp, null);
                        }
                    }
                    else
                    {
                        //虚拟实体（扩展实体）内定义的属性不使用表前缀
                        return GetDbField(queryInstance, cp, null);
                    }
                }
                return GetDbField(queryInstance, cp, tableAttr);
            }
        }

        /// <summary>
        /// 获取属性对应的数据库字段，如果有配置在Fields则采用配置，否则取属性的定义
        /// </summary>        
        /// <param name="configIndex">配置项索引，0：select  1:where  2: order </param>
        /// <returns></returns>
        string GetQueryField(QueryEntityInstance queryInstance, QueryField qf, int configIndex, DBTableAttribute tableAttr)
        {
            string[] configArr; //自定义列，如果有配置中有，则用配置（比如没定义在实在中的其它表字段） 
            bool returnConfig = false;
            string dbFileName = null;
            string entityFieldName;
            if (qf.CustomValue != null)
            {
                entityFieldName = qf.CustomValue;
                if (queryInstance.Config.Fields.TryGetValue(qf.CustomValue, out configArr) && configArr.Length != 0)
                {
                    //直接传一个在实体中没有但在配置中有的列
                    returnConfig = true;
                }
                else
                {
                    //使用自定义列
                    if (queryInstance.Param.StrictModel.Value && qf.CustomValueStrictModel) throw new ClientException("严格模式下不允许使用非配置中的自定义列" + qf.CustomValue);
                    dbFileName = qf.CustomValue;
                }
            }
            else
            {
                entityFieldName = qf.Info.Name;
                if (queryInstance.Config.Fields.TryGetValue(qf.Info.Name, out configArr) && configArr.Length != 0) returnConfig = true;
            }
            if (returnConfig)
            {
                if (configArr.Length > configIndex) dbFileName = configArr[configIndex];
                else dbFileName = configArr[0];
            }
            if (dbFileName == null)
            {

                //DBTableAttribute tableAttr = queryInstance.GetTableAttr();
                if (tableAttr.IsVirtual)
                {
                    if (qf.Info.DeclaringType != queryInstance.Param.entityType)
                    {
                        //虚拟实体（扩展实体）父类的属性，取父类的字段定义
                        DBTableAttribute declareTableAttre = GetTableAttr(qf.Info.DeclaringType, false);
                        if (declareTableAttre.TableName != null)
                        {
                            dbFileName = GetDbField(queryInstance, qf, declareTableAttre);
                        }
                        else
                        {
                            dbFileName = GetDbField(queryInstance, qf, null);
                        }
                    }
                    else
                    {
                        //虚拟实体（扩展实体）内定义的属性不使用表前缀
                        dbFileName = GetDbField(queryInstance, qf, null);
                    }
                }
                else
                {
                    //非虚拟实体，取该属性对应的字段定义
                    dbFileName = GetDbField(queryInstance, qf, tableAttr);
                }
                bool existsNotAllow = false;
                foreach (string str in queryInstance.Config.NotAllowQuery)
                {
                    if (qf.Info.Name == str) { existsNotAllow = true; break; }; // throw new ClientException("不允许查询" + str+"列");
                }
                if (existsNotAllow) return null;

            }

            //是否需要重命名 
            if (configIndex == 0)
            {
                GetDBAccess().AppendFieldAlaisName(ref dbFileName, entityFieldName);
            }
            return dbFileName;
        }

        /// <summary>
        /// 用来格式化的数据源，比如{LoginUserId}
        /// </summary>
        public Hashtable FormatDataSource { get; set; }

        /// <summary>
        /// 用来格式化的数据源，比如{LoginUserId}
        /// </summary>
        /// <param name="source">变量hashtable</param>
        public string FormatFromSource(string str)
        {
            if (FormatDataSource == null) return str;
            return Utility.FormatTemplate(str, FormatDataSource);
            //if (FormatDataSource == null) return str;
            //Regex reg = new Regex(@"\{(\w+?)\}");
            //MatchCollection mc = reg.Matches(str);
            //foreach (Match m in mc)
            //{
            //    if (FormatDataSource[m.Value] != null)
            //    {
            //        if (!FormatDataSource.ContainsKey(m.Value)) throw new FormatSourceNoFoundException(m.Value);
            //        str = str.Replace(m.Value, FormatDataSource[m.Value].ToString());
            //    }
            //}
            //return str;

        }

        public class EntityInstanceParseInfo
        {
            public int editFlag = 1; //当有editflag属性，并且为空或者0的时候不操作数据  
            public string primaryKey = null;
            public object primaryKeyVal = 0;
            //public PropertyInfo primaryKeyPro = null;
            public DBTableAttribute tableAttr;
            public CustomerProperty primaryCusPro;
            /// <summary>
            /// 除主键外的属性字典，以名字为Key
            /// </summary>
            public Dictionary<string, ValueCustomerProperty> proListExcludePrimary = new Dictionary<string, ValueCustomerProperty>();
            public Dictionary<string, object> proItemsList = new Dictionary<string, object>();
            /// <summary>
            /// 子元素（List）的集合
            /// </summary>
            public Dictionary<string, Type> proItemsDefList = new Dictionary<string, Type>();

            /// <summary>
            /// 带属性Property值的CustomerProperty
            /// </summary>
            public class ValueCustomerProperty
            {
                public CustomerProperty CusProperty { get; set; }
                public object PropertyValue { get; set; }
            }

        }

        /// <summary>
        /// 获取实体的表定义
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public DBTableAttribute GetTableAttr(Type entityType, bool useEntityNameWhenNull = true)
        {
            var rewriteAttr = this.GetArgument<DBTableAttribute>("__REWRITE_TABLE_ATTR_" + entityType.Name + "__");
            if (rewriteAttr != null) return rewriteAttr;
            else return GET_TABLE_ATTR_STATIC(entityType, useEntityNameWhenNull);
        }

        /// <summary>  
        /// 重写当前过程实体的表级属于，比如原来实体定义了表名，但在该过程想使用另一个表名  
        /// </summary>  

        public void RewriteTableAttr<T>(DBTableAttribute tableAttr)
        {
            this.SetArgument("__REWRITE_TABLE_ATTR_" + typeof(T).Name + "__", tableAttr);
        }

        private EntityInstanceParseInfo ParseCustomerAttr(Type entityType, IDBEntity entityObj)
        {
            EntityLoaderInfo loaderInfo = EntityLoaderInfo.GetEntityLoaderInfo(entityType);
            if (loaderInfo.OverrideTableInfo != null)
            {
                //是否重写表名
                string tableName = loaderInfo.OverrideTableInfo.GetValue(entityObj) as string;
                if (!string.IsNullOrEmpty(tableName))
                    this.SetArgument("__REWRITE_TABLE_ATTR_" + entityType.Name + "__", new DBTableAttribute { TableName = tableName });
            }
            stepMsg = "Parse " + entityType.Name + " CustomerAttr";
            EntityInstanceParseInfo parseInfo = new EntityInstanceParseInfo();
            parseInfo.tableAttr = GetTableAttr(entityType);
            foreach (PropertyInfo proInfo in entityType.GetProperties())
            {
                if (proInfo.GetGetMethod() == null) continue;
                CustomerProperty cusPro = loaderInfo.GetCustomerProperty(proInfo.Name);
                if (cusPro == null || (cusPro.Attr != null && !cusPro.Attr.IsDBField(this))) continue;
                object proVal = entityObj == null ? null : proInfo.GetValue(entityObj, null);
                string fieldName = cusPro.GetDBFieldName(entityObj);
                if (cusPro.IsPrimaryKey())
                {
                    parseInfo.primaryCusPro = cusPro;
                    parseInfo.primaryKey = fieldName;
                    //parseInfo.primaryKeyPro = proInfo;
                    parseInfo.primaryKeyVal = proVal;
                    continue;
                }
                Type proinfoType = proInfo.PropertyType;
                // if (proinfoType.BaseType == null) throw new Exception("属性" + proinfoType.Name + "的类型不正确,没有BaseType,通常这种情况为定义了Object类型");
                if (proinfoType.BaseType != null && proinfoType.BaseType.Name.IndexOf("List") > -1) proinfoType = proinfoType.BaseType; //对自定义集合类的支持，需要继承List<T>
                switch (proinfoType.Namespace)
                {
                    case "System": //简单类型                        
                        if (proVal != null && !entityObj.ValueIsNull(proInfo))
                        {
                            if (proInfo.Name.ToLower() == "editflag")
                            {
                                if (proinfoType.Name != "Int32") throw new ClientException("EditFlag属性必需为int值");
                                parseInfo.editFlag = Convert.ToInt32(proVal);
                            }
                            else
                            {

                                parseInfo.editFlag = 1;
                                parseInfo.proListExcludePrimary.Add(cusPro.Info.Name, new EntityInstanceParseInfo.ValueCustomerProperty() { CusProperty = cusPro, PropertyValue = proVal });
                            }
                        }
                        else
                        {
                            //值为空，看是否开启为空也保存
                            if (cusPro.Attr != null)
                            {
                                if (!cusPro.Attr.IsDBField(this)) break;
                            }
                            var queryInstance = Thread.GetData(Thread.GetNamedDataSlot("queryInstance")) as QueryEntityInstance;
                            if (queryInstance != null && queryInstance.Config.IgnoreNull != null)
                            {
                                foreach (string ignoreField in queryInstance.Config.IgnoreNull)
                                {
                                    if (ignoreField != null && ignoreField.Equals(proInfo.Name))
                                    {
                                        parseInfo.proListExcludePrimary.Add(cusPro.Info.Name, new EntityInstanceParseInfo.ValueCustomerProperty() { CusProperty = cusPro, PropertyValue = proVal });
                                        break;
                                    }
                                }
                            }
                        }
                        break;
                    case "System.Collections.Generic":
                        Type type = GetIDBEntityListItemType(proinfoType);
                        if (type != null)
                        {
                            if (proVal != null) parseInfo.proItemsList.Add(proInfo.Name, proVal);
                            parseInfo.proItemsDefList.Add(proInfo.Name, type);
                        }
                        break;
                    default:
                        if (proinfoType.IsSubclassOf(typeof(IDBEntity))) parseInfo.proItemsDefList.Add(proInfo.Name, proinfoType);
                        break;
                }
            }
            return parseInfo;
        }

        private static Type GetIDBEntityListItemType(Type proinfoType)
        {
            Type[] typeArr = proinfoType.GetGenericArguments();
            if (typeArr.Length > 0 && typeArr[0].IsSubclassOf(typeof(IDBEntity)))
                return typeArr[0];
            else return null;
        }

        // private static Type GetIDBEntityListItemType(object proinfoType)
        // {
        //     Type[] typeArr = proinfoType.GetType().GetGenericArguments();
        //     if (typeArr.Length > 0 && typeArr[0].IsSubclassOf(typeof(IDBEntity)))
        //         return typeArr[0];
        //     else return null;
        // }

        private string FormatValueForDB(PropertyInfo info, object value)
        {
            if (value == null) return "null";
            Type t;
            if (!info.PropertyType.IsGenericType)
            {
                t = info.PropertyType;
            }
            else
            {
                //泛型Nullable<>
                Type genericTypeDefinition = info.PropertyType.GetGenericTypeDefinition();
                if (genericTypeDefinition == typeof(Nullable<>))
                {
                    t = Nullable.GetUnderlyingType(info.PropertyType);
                }
                else return "null";
            }
            switch (t.Name)
            {
                case "Int32":
                case "Int64":
                case "Single":
                case "Double":
                case "Decimal":
                    return value.ToString();
                case "Boolean":
                    return value.Equals(true) ? "1" : "0";
                default:
                    return "'" + value + "'";
            }
        }

        private object GetIdentityValue(string tableName, string primaryKey)
        {
            object identity;
            string identitySql = GetDBAccess().GetNewIdentitySql(tableName);
            if (string.IsNullOrEmpty(identitySql))
            {
                if (!DBContext.UserRedis) throw new ClientException("数据库不支持自增，需要使用redis支持！");
                //如果使用redis缓存 ，则使得缓存来实现自增                              
                identity = this.Membership.GetCustomIdentityValue(tableName, primaryKey, this);
            }
            else
            {
                //使用数据库的自增（GetIdentitySql）
                // sql += primaryKey + ",";
                object scalar = GetDBAccess().ExecScalar(identitySql, CommandType.Text);
                if (scalar == null || scalar == DBNull.Value) throw new ClientException("自动获取主键失败");
                identity = Convert.ToInt64(scalar);
            }
            return identity;
        }
        /// <summary>
        /// 保存实体到数据库操作
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="rootParseInfo">主表则为空，子表则执行下带入</param>
        /// <param name="filterPropertys">过滤的(需要保存和更新的)属性列表</param>
        private int SaveEntity(QueryEntityInstance queryInstance, IDBEntity obj, EntityInstanceParseInfo rootParseInfo, string[] filterPropertyArr = null, bool treeParentChange = false)
        {
            Type entityType = obj.GetType();
            EntityLoaderInfo loaderInfo = EntityLoaderInfo.GetEntityLoaderInfo(entityType);
            if (queryInstance.Param.StrictModel.Value && queryInstance.Config.NotAllowSaving.Length > 0 && queryInstance.Config.NotAllowSaving[0] == "*") throw new ClientException("当前的配置不允许对" + entityType.Name + "进行更改操作！");
            stepMsg = "开始保存" + entityType.Name;
            EntityInstanceParseInfo parseInfo = ParseCustomerAttr(entityType, obj);
            //if (parseInfo.proListExcludePrimary.Count == 0 ) throw new ClientException("没有要操作的列");
            if (parseInfo.editFlag == 0) return -1;
            int effectCount = -1;
            if (string.IsNullOrEmpty(parseInfo.primaryKey) || parseInfo.primaryCusPro == null) throw new ClientException(obj.GetType().Name + "的DBTableAttribute属性没有定义主键");
            string sql = "";
            bool isNew = obj.ValueIsNull(parseInfo.primaryCusPro.Info) || parseInfo.primaryKeyVal.ToString().Equals("0");
            if (isNew)
            {
                //如果有标记删除的列，并且没有值的，比如Status，赋值1
                if (loaderInfo.MarkDeleteCusPro != null)
                {
                    CustomerProperty markDelCus = loaderInfo.MarkDeleteCusPro;
                    Object o = markDelCus.Info.GetValue(obj, null);
                    if (o == null || o.Equals(IDBEntity.DefaultNullValue))
                    {
                        markDelCus.Info.SetValue(obj, markDelCus.Attr.MarkDeleteValue[0], null);
                        if (!parseInfo.proListExcludePrimary.ContainsKey(markDelCus.Info.Name))
                        {
                            parseInfo.proListExcludePrimary.Add(markDelCus.Info.Name, new EntityInstanceParseInfo.ValueCustomerProperty() { CusProperty = markDelCus, PropertyValue = markDelCus.Attr.MarkDeleteValue[0] });
                        }
                    }
                }
            }
            //如果是树型的实体，当code没赋值的时候，自动赋值
            CustomerProperty parentProperty = null;
            if (obj is ITreeDBEntity && !parseInfo.tableAttr.IsVirtual)
            {
                if (isNew) parentProperty = OnSaveNewTree(queryInstance, obj, parseInfo);
                else if (treeParentChange)
                {
                    if (parseInfo.tableAttr.TreeMode != DBTreeMode.LevelTable) throw new ClientException("不支持非LevelTable的TreeEntity修改Parent");
                    parentProperty = queryInstance.Param.LoaderInfo.GetParentCustomerProperty();
                }
            }
            Dictionary<string, EntityInstanceParseInfo.ValueCustomerProperty> filterPropertys;
            if (filterPropertyArr == null) filterPropertys = parseInfo.proListExcludePrimary;
            else
            {
                filterPropertys = new Dictionary<string, EntityInstanceParseInfo.ValueCustomerProperty>();
                foreach (string proName in filterPropertyArr)
                {
                    if (parseInfo.proListExcludePrimary.ContainsKey(proName))
                    {
                        filterPropertys.Add(proName, parseInfo.proListExcludePrimary[proName]);
                    }

                }
            }

            if (filterPropertys.Count > 0)
            {

                List<IDbDataParameter> parameters = new List<IDbDataParameter>();
                if (isNew)
                {
                    stepMsg = "生成插入语句";
                    sql = "insert into " + parseInfo.tableAttr.TableName + " (";
                    var customIncream = !GetDBAccess().AotoIdentity || !parseInfo.primaryCusPro.Attr.Identity;
                    //如果不支持自动增长，或者主键没显示定义自动增长
                    if (customIncream)
                    {
                        object idetity = GetIdentityValue(parseInfo.tableAttr.TableName, parseInfo.primaryCusPro.GetDBFieldName(obj));
                        parseInfo.primaryKeyVal = Convert.ChangeType(idetity, parseInfo.primaryCusPro.Info.PropertyType);
                        parseInfo.primaryCusPro.Info.SetValue(obj, parseInfo.primaryKeyVal, null);
                        sql += parseInfo.primaryCusPro.GetDBFieldName(obj) + ",";
                    }

                    foreach (KeyValuePair<string, EntityInstanceParseInfo.ValueCustomerProperty> kv in filterPropertys) sql += kv.Value.CusProperty.GetDBFieldName(obj) + ",";
                    sql = sql.Substring(0, sql.Length - 1);
                    sql += ") values(";
                    if (customIncream)
                    {
                        IDbDataParameter parameter = GetDBAccess().CreateParameter(parseInfo.primaryCusPro.GetDBFieldName(obj), parseInfo.primaryKeyVal);
                        sql += parameter.ParameterName + ",";
                        parameters.Add(parameter);
                    }
                    if (queryInstance.Param.StrictModel.Value && rootParseInfo == null)
                    {
                        foreach (string str in queryInstance.Config.NotAllowSaving)
                        {
                            if (filterPropertys.ContainsKey(str)) throw new ClientException("当前的Permission配置，不允许修改" + str + "列的值");
                        }
                    }
                    foreach (KeyValuePair<string, EntityInstanceParseInfo.ValueCustomerProperty> kv in filterPropertys)
                    {

                        // FormatValueForDB(kv.Key.Info, kv.Value)
                        IDbDataParameter parameter = GetDBAccess().CreateParameter(kv.Value.CusProperty.GetDBFieldName(obj), kv.Value.PropertyValue);
                        sql += parameter.ParameterName + ",";
                        parameters.Add(parameter);
                    }
                    sql = sql.Substring(0, sql.Length - 1);
                    sql += ")";
                    if (!customIncream)//&& parseInfo.primaryCusPro.Info.PropertyType == typeof(int)
                    {
                        sql += ";" + GetDBAccess().GetInsertedIdentitySql(parseInfo.tableAttr.TableName);
                        stepMsg = "执行插入语句";
                        object scalar = GetDBAccess().ExecScalar(sql, CommandType.Text, parameters.ToArray());
                        if (scalar == null || scalar == DBNull.Value) throw new ClientException("自动获取主键失败");
                        parseInfo.primaryKeyVal = Convert.ChangeType(scalar, parseInfo.primaryCusPro.Info.PropertyType);
                        parseInfo.primaryCusPro.Info.SetValue(obj, parseInfo.primaryKeyVal, null);
                    }
                    else
                    {
                        stepMsg = "执行插入语句";
                        effectCount = GetDBAccess().ExecuteCommand(sql, CommandType.Text, parameters.ToArray());
                    }
                    if (obj is ITreeDBEntity && parseInfo.tableAttr.TreeMode == DBTreeMode.LevelTable) OnSaveTreeReation(obj, parseInfo, parentProperty, null);
                }
                else
                {
                    //是否删除
                    if (parseInfo.editFlag == 2)
                    {
                        stepMsg = "生成删除语句";
                        sql = "delete from " + parseInfo.tableAttr.TableName + " where  " + parseInfo.primaryCusPro.GetDBFieldName(obj) + " = '" + parseInfo.primaryKeyVal + "'";
                        effectCount = GetDBAccess().ExecuteCommand(sql);
                        CheckTreeDelete(queryInstance, entityType, parseInfo);
                    }
                    else
                    {
                        if (rootParseInfo == null)
                        {
                            foreach (string str in queryInstance.Config.NotAllowSaving)
                            {
                                if (filterPropertys.ContainsKey(str)) throw new ClientException("当前的Permission配置，不允许修改" + str + "列的值");
                            }
                        }
                        stepMsg = "生成更新语句";
                        sql = "update " + parseInfo.tableAttr.TableName + " set ";
                        foreach (KeyValuePair<string, EntityInstanceParseInfo.ValueCustomerProperty> kv in filterPropertys)
                        {

                            string fieldName = kv.Value.CusProperty.GetDBFieldName(obj);
                            IDbDataParameter parameter = GetDBAccess().CreateParameter(fieldName, kv.Value.PropertyValue);
                            if (parameter.Value == null || parameter.Value.Equals(IDBEntity.DbNullString) || parameter.Value.Equals(IDBEntity.DefaultNullValue) || parameter.Value.Equals(IDBEntity.DefaultDoubleValue)) parameter.Value = DBNull.Value;
                            sql += fieldName + "=" + parameter.ParameterName + ",";
                            parameters.Add(parameter);
                        }
                        sql = sql.Substring(0, sql.Length - 1);
                        sql += " where " + parseInfo.primaryCusPro.GetDBFieldName(obj) + " = '" + parseInfo.primaryKeyVal + "'";
                        stepMsg = "执行更新语句";
                        effectCount = GetDBAccess().ExecuteCommand(sql, CommandType.Text, parameters.ToArray());
                        if (parentProperty != null && obj is ITreeDBEntity && parseInfo.tableAttr.TreeMode == DBTreeMode.LevelTable)
                        {
                            OnSaveTreeReation(obj, parseInfo, parentProperty, parentProperty);
                        }
                    }
                }
            }
            if (rootParseInfo == null) rootParseInfo = parseInfo;
            object mainPrimaryVal = parseInfo.primaryCusPro.Info.GetValue(obj, null);
            foreach (KeyValuePair<string, object> kv in parseInfo.proItemsList)
            {
                if (kv.Value is IEnumerable)
                {
                    //清空原来的子表,子元素。是否有editflag
                    bool isFirst = true;
                    foreach (IDBEntity en in ((IEnumerable)kv.Value))
                    {
                        CustomerProperty foreignCP = SetForeignVal(en, obj, parseInfo, rootParseInfo);
                        if (isFirst)
                        {
                            PropertyInfo pinfo = en.GetType().GetProperty("EditFlag");
                            if (pinfo == null)
                            {
                                //没有editflag，先清空子表
                                var tableName = GetTableAttr(en.GetType()).TableName;
                                //外键对应的主表的字段（不一定就是主键） 
                                CustomerProperty mainCP = loaderInfo.GetCustomerProperty(foreignCP.Attr.ForeignProperty);
                                if (mainCP == null) throw new ClientException("外键对应的主表字段未定义!");
                                ExecuteCommand("delete from " + tableName + " where " + foreignCP.GetDBFieldName(obj) + "='" + mainCP.Info.GetValue(obj, null) + "'");
                            }
                            isFirst = false;
                        }

                        SaveEntity(queryInstance, en, rootParseInfo);
                    }
                }
                else
                {
                    SetForeignVal(kv.Value, obj, parseInfo, rootParseInfo);
                    SaveEntity(queryInstance, (IDBEntity)kv.Value, rootParseInfo);
                }
            }

            if (m_updatingWatchs.IndexOf(entityType) > -1 && OnEntityUpdated != null)
            {
                OnEntityUpdated(this, obj, isNew);
            }
            return effectCount;
        }

        /// <summary>
        /// 保存实体到数据库操作
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="rootParseInfo">主表则为空，子表则执行下带入</param>
        /// <param name="filterPropertys">过滤的(需要保存和更新的)属性列表</param>
        private int SaveNewEntity(QueryEntityInstance queryInstance, IDBEntity obj, EntityInstanceParseInfo rootParseInfo, string[] filterPropertyArr = null, bool treeParentChange = false)
        {
            Type entityType = obj.GetType();
            EntityLoaderInfo loaderInfo = EntityLoaderInfo.GetEntityLoaderInfo(entityType);
            if (queryInstance.Param.StrictModel.Value && queryInstance.Config.NotAllowSaving.Length > 0 && queryInstance.Config.NotAllowSaving[0] == "*") throw new ClientException("当前的配置不允许对" + entityType.Name + "进行更改操作！");
            stepMsg = "开始保存" + entityType.Name;
            EntityInstanceParseInfo parseInfo = ParseCustomerAttr(entityType, obj);
            //if (parseInfo.proListExcludePrimary.Count == 0 ) throw new ClientException("没有要操作的列");
            if (parseInfo.editFlag == 0) return -1;
            int effectCount = -1;
            if (string.IsNullOrEmpty(parseInfo.primaryKey) || parseInfo.primaryCusPro == null) throw new ClientException(obj.GetType().Name + "的DBTableAttribute属性没有定义主键");
            string sql = "";
            bool isNew = true;
            bool hasPKValue = !(obj.ValueIsNull(parseInfo.primaryCusPro.Info) || parseInfo.primaryKeyVal.ToString().Equals("0"));
            //如果有标记删除的列，并且没有值的，比如Status，赋值1
            if (loaderInfo.MarkDeleteCusPro != null)
            {
                CustomerProperty markDelCus = loaderInfo.MarkDeleteCusPro;
                Object o = markDelCus.Info.GetValue(obj, null);
                if (o == null || o.Equals(IDBEntity.DefaultNullValue))
                {
                    markDelCus.Info.SetValue(obj, markDelCus.Attr.MarkDeleteValue[0], null);
                    if (!parseInfo.proListExcludePrimary.ContainsKey(markDelCus.Info.Name))
                    {
                        parseInfo.proListExcludePrimary.Add(markDelCus.Info.Name, new EntityInstanceParseInfo.ValueCustomerProperty() { CusProperty = markDelCus, PropertyValue = markDelCus.Attr.MarkDeleteValue[0] });
                    }
                }
            }

            //如果是树型的实体，当code没赋值的时候，自动赋值
            CustomerProperty parentProperty = null;
            if (obj is ITreeDBEntity && !parseInfo.tableAttr.IsVirtual)
            {
                if (isNew) parentProperty = OnSaveNewTree(queryInstance, obj, parseInfo);
                else if (treeParentChange)
                {
                    if (parseInfo.tableAttr.TreeMode != DBTreeMode.LevelTable) throw new ClientException("不支持非LevelTable的TreeEntity修改Parent");
                    parentProperty = queryInstance.Param.LoaderInfo.GetParentCustomerProperty();
                }
            }
            Dictionary<string, EntityInstanceParseInfo.ValueCustomerProperty> filterPropertys;
            if (filterPropertyArr == null) filterPropertys = parseInfo.proListExcludePrimary;
            else
            {
                filterPropertys = new Dictionary<string, EntityInstanceParseInfo.ValueCustomerProperty>();
                foreach (string proName in filterPropertyArr)
                {
                    if (parseInfo.proListExcludePrimary.ContainsKey(proName))
                    {
                        filterPropertys.Add(proName, parseInfo.proListExcludePrimary[proName]);
                    }

                }
            }

            if (filterPropertys.Count > 0)
            {

                List<IDbDataParameter> parameters = new List<IDbDataParameter>();

                stepMsg = "生成插入语句";
                var customIncream = false;
                sql = "insert into " + parseInfo.tableAttr.TableName + " (";
                if (hasPKValue)
                {
                    sql += parseInfo.primaryKey + ",";
                    customIncream = true;
                }
                else
                {
                    customIncream = !GetDBAccess().AotoIdentity || !parseInfo.primaryCusPro.Attr.Identity;
                    //如果不支持自动增长，或者主键没显示定义自动增长
                    if (customIncream)
                    {
                        object idetity = GetIdentityValue(parseInfo.tableAttr.TableName, parseInfo.primaryKey);
                        parseInfo.primaryKeyVal = Convert.ChangeType(idetity, parseInfo.primaryCusPro.Info.PropertyType);
                        parseInfo.primaryCusPro.Info.SetValue(obj, parseInfo.primaryKeyVal, null);
                        sql += parseInfo.primaryKey + ",";
                    }
                }
                foreach (KeyValuePair<string, EntityInstanceParseInfo.ValueCustomerProperty> kv in filterPropertys) sql += kv.Value.CusProperty.GetDBFieldName(obj) + ",";
                sql = sql.Substring(0, sql.Length - 1);
                sql += ") values(";
                if (customIncream)
                {
                    IDbDataParameter parameter = GetDBAccess().CreateParameter(parseInfo.primaryCusPro.GetDBFieldName(obj), parseInfo.primaryKeyVal);
                    sql += parameter.ParameterName + ",";
                    parameters.Add(parameter);
                }
                if (queryInstance.Param.StrictModel.Value && rootParseInfo == null)
                {
                    foreach (string str in queryInstance.Config.NotAllowSaving)
                    {
                        if (filterPropertys.ContainsKey(str)) throw new ClientException("当前的Permission配置，不允许修改" + str + "列的值");
                    }
                }
                foreach (KeyValuePair<string, EntityInstanceParseInfo.ValueCustomerProperty> kv in filterPropertys)
                {

                    // FormatValueForDB(kv.Key.Info, kv.Value)
                    IDbDataParameter parameter = GetDBAccess().CreateParameter(kv.Value.CusProperty.GetDBFieldName(obj), kv.Value.PropertyValue);
                    sql += parameter.ParameterName + ",";
                    parameters.Add(parameter);
                }
                sql = sql.Substring(0, sql.Length - 1);
                sql += ")";
                if (!customIncream)
                {
                    sql += ";" + GetDBAccess().GetInsertedIdentitySql(parseInfo.tableAttr.TableName);
                    stepMsg = "执行插入语句";
                    object scalar = GetDBAccess().ExecScalar(sql, CommandType.Text, parameters.ToArray());
                    if (scalar == null || scalar == DBNull.Value) throw new ClientException("自动获取主键失败");
                    parseInfo.primaryKeyVal = Convert.ChangeType(scalar, parseInfo.primaryCusPro.Info.PropertyType);
                    parseInfo.primaryCusPro.Info.SetValue(obj, parseInfo.primaryKeyVal, null);
                }
                else
                {
                    stepMsg = "执行插入语句";
                    effectCount = GetDBAccess().ExecuteCommand(sql, CommandType.Text, parameters.ToArray());
                }
                if (obj is ITreeDBEntity && parseInfo.tableAttr.TreeMode == DBTreeMode.LevelTable) OnSaveTreeReation(obj, parseInfo, parentProperty, null);
            }
            if (rootParseInfo == null) rootParseInfo = parseInfo;
            object mainPrimaryVal = parseInfo.primaryCusPro.Info.GetValue(obj, null);
            foreach (KeyValuePair<string, object> kv in parseInfo.proItemsList)
            {
                if (kv.Value is IEnumerable)
                {
                    //清空原来的子表,子元素。是否有editflag
                    bool isFirst = true;
                    foreach (IDBEntity en in ((IEnumerable)kv.Value))
                    {
                        CustomerProperty foreignCP = SetForeignVal(en, obj, parseInfo, rootParseInfo);
                        if (isFirst)
                        {
                            PropertyInfo pinfo = en.GetType().GetProperty("EditFlag");
                            if (pinfo == null)
                            {
                                //没有editflag，先清空子表
                                var tableName = GetTableAttr(en.GetType()).TableName;
                                //外键对应的主表的字段（不一定就是主键） 
                                CustomerProperty mainCP = loaderInfo.GetCustomerProperty(foreignCP.Attr.ForeignProperty);
                                if (mainCP == null) throw new ClientException("外键对应的主表字段未定义!");
                                ExecuteCommand("delete from " + tableName + " where " + foreignCP.GetDBFieldName(obj) + "='" + mainCP.Info.GetValue(obj, null) + "'");
                            }
                            isFirst = false;
                        }

                        SaveNewEntity(queryInstance, en, rootParseInfo);
                    }
                }
                else
                {
                    SetForeignVal(kv.Value, obj, parseInfo, rootParseInfo);
                    SaveNewEntity(queryInstance, (IDBEntity)kv.Value, rootParseInfo);
                }
            }

            if (m_updatingWatchs.IndexOf(entityType) > -1 && OnEntityUpdated != null)
            {
                OnEntityUpdated(this, obj, isNew);
            }
            return effectCount;
        }

        //树弄实体，自动编号，返回父结点
        private CustomerProperty OnSaveNewTree(QueryEntityInstance queryInstance, IDBEntity obj, EntityInstanceParseInfo parseInfo)
        {
            Type entityType = obj.GetType();
            DBTableAttribute tableAttr = GetTableAttr(entityType);
            int codeLength = tableAttr.TreeCodeLenth; //编号的长度，默认为2，比如AA，AAAB
            if (codeLength == 0) codeLength = 2;
            CustomerProperty cp = queryInstance.Param.LoaderInfo.GetParentCustomerProperty();
            //if (cp.Info.PropertyType == typeof(int) && obj.ValueIsNull(cp.Info)) throw new Exception("Parent外键未赋值");
            object parentVal = cp.Info.GetValue(obj, null);
            if (string.Empty.Equals(parentVal) || parentVal == null)
            {
                cp.Info.SetValue(obj, null); //父编号如果是传空字符串，则为空
                parentVal = null;
            }
            // throw new ClientException ("Parent外键没定义或者没有对应的主键配置!");
            CustomerProperty primaryCodeCP = queryInstance.Param.LoaderInfo.GetCustomerProperty(cp.Attr.ForeignProperty);
            bool isForeignSelf = primaryCodeCP != null && (cp.Attr.ForeignTable == null || cp.Attr.ForeignTable == tableAttr.TableName);
            if (isForeignSelf && !primaryCodeCP.IsPrimaryKey())
            {
                if (tableAttr.TreeMode == DBTreeMode.Code)
                {

                    //if（新增操作 && 外键对应的键不是主键 && 外键对应的表是自己 ） 自动给code编号
                    //获取parent下最大的code
                    string parentFieldName = cp.GetDBFieldName(obj);
                    string sql = "select max(" + primaryCodeCP.GetDBFieldName(obj) + ") from " + tableAttr.TableName + " where ";
                    if (parentVal == null) sql += "(" + parentFieldName + " is null or  " + parentFieldName + " = '0' )";
                    else sql += parentFieldName + " = '" + parentVal + "' ";
                    object scalar = ExecScalar(sql);
                    if (scalar == DBNull.Value)
                    {
                        if (parentVal == null) scalar = "A".PadLeft(codeLength, 'A');
                        else scalar = parentVal + "A".PadLeft(codeLength, 'A');
                    }
                    else
                    {
                        string maxValStr = scalar.ToString();
                        string str = Utility.Code26Add(maxValStr, 1);
                        if (str.Length < codeLength) str = str.PadLeft(codeLength, 'A');
                        else if (str.Length > maxValStr.Length) throw new ClientException("超过允许的子结点的最大数量");
                        scalar = str;
                    }
                    primaryCodeCP.Info.SetValue(obj, scalar, null);
                    LogMessage(entityType.Name + "自动编号" + scalar, "SaveEntity");
                    if (!parseInfo.proListExcludePrimary.ContainsKey(primaryCodeCP.Info.Name))
                    {
                        parseInfo.proListExcludePrimary.Add(primaryCodeCP.Info.Name, new EntityInstanceParseInfo.ValueCustomerProperty() { PropertyValue = scalar, CusProperty = primaryCodeCP });
                    }
                }
                else if (tableAttr.TreeMode == DBTreeMode.LevelTable)
                {

                }
            }
            return cp;
        }

        private void OnSaveTreeReation(IDBEntity obj, EntityInstanceParseInfo parseInfo, CustomerProperty parentProperty, object oldParentValue)
        {

            //用另一张表记录层级关系
            string rexTable = parseInfo.tableAttr.TableName + "_REX";
            object parentVal = parentProperty.Info.GetValue(obj, null);
            if (oldParentValue != null)
            {
                //如果有更新推荐人等关系的字段，需要先删除原来的上级关系 
                object pkValue = obj.GetPrimaryValue();
                //查找所有下级
                DataTable dt = QueryTable("select " + rexTable + @".*,parent.NodeId ParentNodeId from " + rexTable + @"
left join " + rexTable + @" parent on  parent.SubNodeId =" + rexTable + @".SubNodeId and parent.Deep =1
 where " + rexTable + @".NodeId = '" + pkValue + "'");
                //删除原来所有下级
                ExecuteCommand("DELETE from " + rexTable + " where SubNodeId='" + pkValue + "' or SubNodeId in (select t.SubNodeId from " + rexTable + " t where t.NodeId = '" + pkValue + "' )");
                //保存自己
                InsertARex(rexTable, parentVal, pkValue);
                //按层级重组所有下级
                int deep = 1;
                while (dt.Rows.Count > 0)
                {
                    DataRow[] dataRows = dt.Select("Deep = " + deep);
                    if (dataRows.Length == 0) break;
                    foreach (DataRow dr in dataRows)
                    {
                        InsertARex(rexTable, dr["ParentNodeId"].ToString(), dr["SubNodeId"].ToString());
                    }
                    deep++;
                }
            }
            else
            {
                //新设置推荐关系（比如新用户）
                if (parentVal == null || parentVal.ToString().Equals("0")) return;
                InsertARex(rexTable, parentVal, obj.GetPrimaryValue());
            }

        }

        private void InsertARex(string rexTable, object parentVal, object pkValue)
        {
            if (parentVal.Equals(0)) return;
            //上级结点添加关系
            string sql = "insert into " + rexTable + " (NodeId,Deep,SubNodeId) values( '" + parentVal + "',1,'" + pkValue + "')";
            ExecuteCommand(sql);
            //上级的所有上级，添加新结点关系
            sql = "insert into " + rexTable + " (NodeId,Deep,SubNodeId) select  NodeId,Deep+1,'" + pkValue + "' from " + rexTable + " where NodeId <> '0' and SubNodeId ='" + parentVal + "' ";
            ExecuteCommand(sql);
        }

        public void Rex_ReCreate<T>() where T : IDBEntity
        {
            EntityInstanceParseInfo parseInfo = ParseCustomerAttr(typeof(T), null);
            CustomerProperty customerProperty = getForeignProperry(typeof(T), parseInfo);
            if (customerProperty == null) throw new Exception(typeof(T).Name + "外键定义异常！");
            List<string> userQueue = new List<string>();
            ExecuteCommand("delete from " + parseInfo.tableAttr.TableName + "_REX");
            List<T> rootUsers = QueryManySql<T>("select * from " + parseInfo.tableAttr.TableName + " where (" + customerProperty.GetDBFieldName(null) + "= '0' or " + customerProperty.GetDBFieldName(null) + " is null)");
            foreach (IDBEntity u in rootUsers)
            {
                Rex_DiGuiReCreate<T>(u.GetPrimaryValue().ToString(), parseInfo.tableAttr.TableName, userQueue, customerProperty);
            }
        }

        private void Rex_DiGuiReCreate<T>(string parentId, string tableName, List<string> userQueue, CustomerProperty customerProperty) where T : IDBEntity
        {
            List<T> rootUsers = QueryManySql<T>("select * from " + tableName + " where " + customerProperty.GetDBFieldName(null) + "= '" + parentId + "' ");
            if (rootUsers.Count == 0) return;
            userQueue.Add(parentId);
            foreach (IDBEntity u in rootUsers)
            {
                string primaryValue = u.GetPrimaryValue().ToString();
                for (int i = userQueue.Count - 1; i > -1; i--)
                {
                    int level = userQueue.Count - i;
                    string sql = "insert into " + tableName + "_REX (NodeId,Deep,SubNodeId) values( '" + userQueue[i] + "'," + level + ",'" + primaryValue + "')";
                    ExecuteCommand(sql);
                }
                Rex_DiGuiReCreate<T>(primaryValue, tableName, userQueue, customerProperty);
            }
            userQueue.Remove(parentId);
        }




        private void CheckTreeDelete(QueryEntityInstance queryInstance, Type entityType, EntityInstanceParseInfo parseInfo)
        {
            if (!entityType.IsSubclassOf(typeof(ITreeDBEntity))) return;
            CustomerProperty parentProperty = null;
            foreach (CustomerProperty pro in queryInstance.Param.LoaderInfo.ForeignCusPros)
            {
                if (pro.Attr.ForeignTable == parseInfo.tableAttr.TableName)
                {
                    parentProperty = pro;
                }
            }
            if (parentProperty == null) throw new Exception("没有Parent外键");
            string rexTable = null;
            //判断是否有下级
            string existsChildSql;
            switch (parseInfo.tableAttr.TreeMode)
            {
                case DBTreeMode.Code:
                    {
                        //scalar = ExecScalar("select top 1 " + parseInfo.primaryKeyVal + " from " + parseInfo.tableAttr.TableName + "  where " + parentProperty.GetDBFieldName(null) + " = '" + parseInfo.primaryKeyVal + "'");
                        existsChildSql = "select " + parseInfo.primaryKeyVal + " from " + parseInfo.tableAttr.TableName + "  where " + parentProperty.GetDBFieldName(null) + " = '" + parseInfo.primaryKeyVal + "'";
                        break;
                    }
                case DBTreeMode.LevelTable:
                    {
                        rexTable = parseInfo.tableAttr.TableName + "_REX";
                        existsChildSql = "select SubNodeId from " + rexTable + "  where   NodeId =  '" + parseInfo.primaryKeyVal + "'";
                        //scalar = ExecScalar("select top 1 SubNodeId from " + rexTable + "  where   NodeId =  '" + parseInfo.primaryKeyVal + "'");
                        break;
                    }
                default:
                    {
                        throw new NotImplementedException();
                    }
            }
            //if (scalar != null && scalar != DBNull.Value) throw new ClientException("还有下级结点，不允许删除");
            object scalar = ExecScalar("select 1 where exists (" + existsChildSql + ")");
            if (rexTable != null)
            {
                string sql = "delete from " + rexTable + " where SubNodeId ='" + parseInfo.primaryKeyVal + "'";
                ExecuteCommand(sql);
            }
        }
        /// <summary>
        /// 设置外键的值，有主关键关系的表保存的时候用
        /// </summary>
        private CustomerProperty SetForeignVal(object obj, object foreignObj, EntityInstanceParseInfo parseInfo, EntityInstanceParseInfo rootParseInfo)
        {
            if (obj == null) throw new ClientException("SetForeignVal object is null");
            stepMsg = "设置" + obj.GetType().Name + "外键的值";
            //设置外键的值,rootParseInfo主要是解决明细表中有多级，子级对应的主表外键值也要赋值
            CustomerProperty cusPro = getForeignProperry(obj.GetType(), parseInfo);
            if (cusPro == null) throw new Exception(obj.GetType().Name + "外键定义异常！");
            object foreignVal = null;
            if (parseInfo.primaryCusPro == null) throw new Exception("SetForeignVal error,primaryCusPro is null");
            if (cusPro.Attr.ForeignProperty != null && cusPro.Attr.ForeignProperty != parseInfo.primaryCusPro.Info.Name)
            {
                //对应的外键字段有定义
                EntityInstanceParseInfo.ValueCustomerProperty vcp = parseInfo.proListExcludePrimary[cusPro.Attr.ForeignProperty];
                if (vcp != null) foreignVal = vcp.PropertyValue;
                if (foreignVal == null) throw new Exception("没有找到对应外键" + foreignObj.GetType().Name + "." + cusPro.Attr.ForeignProperty + "的值！");
            }
            else
            {
                //没定义，直接用关联表的主键
                foreignVal = parseInfo.primaryKeyVal;
            }
            if (cusPro == null) throw new ClientException(obj.GetType().Name + "没有定义外键，注意：如果是多级，则父编号也要定义为外键！");
            stepMsg = "设置外键" + cusPro.Info.Name;
            cusPro.Info.SetValue(obj, foreignVal, null);
            //CustomerProperty rootCusPro = getForeignProperry(obj.GetType(), rootParseInfo);
            //if (rootCusPro != null)
            //{
            //    stepMsg = "设置外键" + rootCusPro.Info.Name;
            //    rootCusPro.Info.SetValue(obj, rootParseInfo.primaryKeyVal, null);
            //}
            return cusPro;
        }

        private CustomerProperty getForeignProperry(Type type, EntityInstanceParseInfo foreignParse)
        {
            CustomerProperty cusPro = null;
            foreach (CustomerProperty pro in EntityLoaderInfo.GetEntityLoaderInfo(type).ForeignCusPros)
            {
                if (pro.Attr.ForeignTable == foreignParse.tableAttr.TableName)
                {
                    cusPro = pro;
                    if (string.IsNullOrEmpty(pro.Attr.ForeignProperty)) pro.Attr.ForeignProperty = foreignParse.primaryKey;
                    break;

                }
            }
            //if (cusPro == null) throw new Exception(type.Name + "外键定义异常！");
            return cusPro;
        }

        /// <summary>
        /// 获取执行的信息
        /// </summary>
        /// <returns></returns>
        public string GetStepMsg()
        {
            return "step:" + stepMsg + " \n lastSql:" + GetDBAccess().GetLastSql();
        }

        /// <summary>
        /// 删除对象
        /// </summary>
        /// <param name="permission">权限配置名</param>
        /// <param name="entityName">对象类型</param>
        /// <param name="value">主键值</param>
        /// <returns></returns>
        public int DoDelete(string permission, string entityName, string value)
        {
            var queryInstance = SetQueryEntityConfig(new QueryParam() { entityName = GetFullName(entityName), permission = permission, StrictModel = true });
            return DoDelete(queryInstance.Param.entityType, null, value);

        }

        /// <summary>
        /// 删除对象
        /// </summary>
        /// <param name="value">主键值</param>
        /// <returns></returns>
        public int DoDelete<T>(string value)
        {
            var queryInstance = SetQueryEntityConfig(new QueryParam() { entityType = typeof(T) });
            return DoDelete(queryInstance.Param.entityType, null, value);

        }

        /// <summary>
        /// 删除对象
        /// </summary>
        /// <param name="value">主键值</param>
        /// <returns></returns>
        public int DoDelete<T>(int value)
        {
            var queryInstance = SetQueryEntityConfig(new QueryParam() { entityType = typeof(T) });
            return DoDelete(queryInstance.Param.entityType, null, value.ToString());

        }

        /// <summary>
        /// 删除对象
        /// </summary>
        /// <param name="entity">对象</param>
        /// <returns></returns>
        public int DoDelete(object entity)
        {
            if (!(entity is IDBEntity)) throw new Exception(entity.GetType().Name + "必需继承IDBEntity");
            var queryInstance = SetQueryEntityConfig(new QueryParam() { entityType = entity.GetType() });
            object val = ((IDBEntity)entity).GetPrimaryValue();
            return DoDelete(queryInstance.Param.entityType, null, val.ToString());

        }

        /// <summary>
        /// 删除对象，如果对象中有定义标记删除的属性，则标记，否则delete
        /// </summary>
        /// <param name="permission"></param>
        /// <param name="entityName"></param>
        /// <param name="primarkeyVal"></param>
        public int DoDelete(Type entityType, string key, string value)
        {
            var queryInstance = Thread.GetData(Thread.GetNamedDataSlot("queryInstance")) as QueryEntityInstance;
            if (queryInstance == null) queryInstance = SetQueryEntityConfig(new QueryParam() { entityType = entityType });
            if (queryInstance.Param.StrictModel.Value && queryInstance.Config.NotAllowDelete) throw new ClientException("当前的Permission配置不允许删除操作！");
            int effectRows = 0;
            stepMsg = "开始删除" + entityType.Name;
            if (string.IsNullOrEmpty(value)) throw new ClientException("删除的条件表达式值不能为空");

            EntityInstanceParseInfo parseInfo = ParseCustomerAttr(entityType, null);
            if (key == null) key = parseInfo.primaryKey;
            string sql;
            string[] primaryKeyValArr;
            if (key == parseInfo.primaryKey) primaryKeyValArr = new string[] { value };
            else
            {
                //根据外键删除时，查询要删除的内容的主键值
                stepMsg = "查询要删除的外键值数组";
                sql = "select " + parseInfo.primaryKey + " from " + parseInfo.tableAttr.TableName + " where " + key + "='" + value + "'";
                DataTable dt = GetDBAccess().QueryTable(sql);
                primaryKeyValArr = new string[dt.Rows.Count];
                for (int i = 0; i < dt.Rows.Count; i++) primaryKeyValArr[i] = dt.Rows[i][0].ToString();
            }
            if (primaryKeyValArr.Length == 0) return 0;
            stepMsg = "执行删除语句";
            foreach (string primaryVal in primaryKeyValArr)
            {
                parseInfo.primaryKeyVal = primaryVal;
                CheckTreeDelete(queryInstance, entityType, parseInfo);
                if (queryInstance.Param.LoaderInfo.MarkDeleteCusPro != null) //标记删除            
                {
                    int delVal = queryInstance.Param.LoaderInfo.MarkDeleteCusPro.Attr.MarkDeleteValue[1];
                    sql = "update " + parseInfo.tableAttr.TableName + " set " + queryInstance.Param.LoaderInfo.MarkDeleteCusPro.GetDBFieldName(null) + "= " + delVal + "  where " + parseInfo.primaryKey + "='" + value + "'";
                }
                else
                {
                    sql = "delete from " + parseInfo.tableAttr.TableName + " where " + parseInfo.primaryKey + "='" + primaryVal + "'";
                }
                effectRows = GetDBAccess().ExecuteCommand(sql);
            }

            //触发删除事件
            foreach (string primaryVal in primaryKeyValArr)
            {
                if (m_updatingWatchs.IndexOf(entityType) > -1 && OnEntityUpdated != null)
                {
                    if (OnEntityDeleted != null)
                    {
                        OnEntityDeleted(this, entityType, primaryVal);
                    }
                }
            }

            //子元素，按外键删除 
            foreach (KeyValuePair<string, Type> items in parseInfo.proItemsDefList)
            {
                CustomerProperty cusPro = getForeignProperry(items.Value, parseInfo);
                if (cusPro == null) continue;
                string fieldName = cusPro.GetDBFieldName(null);
                foreach (string primaryVal in primaryKeyValArr)
                {
                    effectRows += DoDelete(items.Value, fieldName, primaryVal);
                }
            }

            return effectRows;
        }

        List<IBusiness> businessList = new List<IBusiness>();

        public Modals.OEMInfo OEM
        {
            get
            {
                return (Modals.OEMInfo)GetArgument("OEMInfo");
            }
        }
        Hashtable Arguments;

        /// <summary>
        /// 获取DBContext整个访问过程中的参数
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public object GetArgument(string name)
        {
            if (Arguments == null) return null;
            return Arguments[name];
        }

        public T GetArgument<T>(string name)
        {
            object obj = GetArgument(name);
            if (obj == null) return default(T);
            else return (T)obj;
        }

        public bool ContainsArgument(string name)
        {
            if (Arguments == null) return false;
            return Arguments.ContainsKey(name);
        }
        /// <summary>
        /// 存储参数到DBContext整个访问过程都可获取
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public void SetArgument(string name, object value, bool removeNull = true)
        {
            if (Arguments == null) Arguments = new Hashtable();
            if (value == null && removeNull)
            {
                Arguments.Remove(name);
            }
            else
            {
                Arguments[name] = value;
            }
        }

        /// <summary>
        /// 是否是移动端
        /// </summary>
        /// <returns></returns>
        public bool IsMobileDevice
        {
            get
            {
                object obj = GetArgument("IsMobileDevice");
                if (obj == null) throw new ClientException("请先在MemberShip的OnDBContextInit中使用SetArgument来设置IsMobileDevice的值");
                return (bool)obj;
            }
        }

        #region 登录相关
        Membership.BaseUser m_loginUser;
        // TokenInfo m_loginTokenInfo;

        // /// <summary>
        // /// 登录的Token信息
        // /// </summary>
        // public TokenInfo LoginTokenInfo
        // {
        //     get
        //     {
        //         if (m_loginTokenInfo == null)
        //         {
        //             m_loginTokenInfo =Membership.GetTokenInfo(this);
        //         }
        //         return m_loginTokenInfo;
        //     }
        // }

        /// <summary>
        /// 当前用户
        /// </summary>
        public Membership.BaseUser LoginUser
        {
            get
            {
                if (m_loginUser == null && !GetUserHasException)
                {
                    GetUserHasException = true;
                    m_loginUser = Membership.GetUserFrom(this);
                    GetUserHasException = false;
                }
                return m_loginUser;
            }
        }

        private bool GetUserHasException = false;

        // /// <summary>
        // /// 记录登录状态
        // /// </summary>
        // public TokenInfo SetUserLoginState(BaseUser userInfo, LoginUserStateType userStateType, DateTime Expires, LoginPlatfromId platform, object values)
        // {
        //     m_loginTokenInfo = Membership.SetUserLoginState(userInfo, userStateType, Expires, platform, values, this);

        //     m_loginUser = userInfo;
        //     return m_loginTokenInfo;
        // }
        public void SaveUserRecord(BaseUser userInfo, string cityId, string location, int device, int ActionType, int isAdmin, string terminal, string client, string ip)
        {
            MembershipBLL bll = GetBusiness<MembershipBLL>();
            bll.SaveUserRecord(userInfo.UserId, cityId, location, device, 0, isAdmin, terminal, client, ip, userInfo.PushId);
            //更新redis
            if (UserRedis)
            {
                //DeleteRedisItem(membership.UserType.Name + "_" + userInfo.GetPrimaryValue());
                SetRedisItem(membership.UserType.Name + "_" + userInfo.GetPrimaryValue(), userInfo.ToJson());
            }
            m_loginUser = userInfo;
        }
        /// <summary>
        /// 是否有登录
        /// </summary>
        /// <returns></returns>
        public bool IsLogin() { return LoginUser != null; }

        #endregion

        /// <summary>
        /// 获取业务访问类,同个类在一次访问过程只创建一个实例
        /// </summary>        
        public T GetBusiness<T>() where T : IBusiness, new()
        {
            // Type type = typeof(T);
            // if (OnBusinessCreating != null)
            // {
            //     Type rewriteType = OnBusinessCreating(this, type);
            //     if (rewriteType != null) type = rewriteType;
            // }
            // IBusiness bussiness = businessList.Find(X => X.GetType() == type);
            // if (bussiness == null)
            // {
            //     bussiness = Activator.CreateInstance(type) as IBusiness;
            //     if (bussiness == null) throw new Exception("无法实例化IBusiness类型" + type.FullName);
            //     bussiness.SetVisiter(this);
            //     businessList.Add(bussiness);
            // }

            // return (T)bussiness;

            return (T)GetBusiness(typeof(T));
        }

        /// <summary>
        /// 获取业务访问类,同个类在一次访问过程只创建一个实例
        /// </summary>        
        public IBusiness GetBusiness(Type type, bool alwaysCreate = false)
        {
            // if (OnBusinessCreating != null)
            // {
            //     Type rewriteType = OnBusinessCreating(this, type);
            //     if (rewriteType != null) type = rewriteType;
            // }
            IBusiness bussiness = null;
            if (alwaysCreate == false)
            {
                bussiness = businessList.Find(X => X.GetType() == type);
            }
            if (bussiness == null)
            {
                bussiness = Membership.CreateServiceInstance(type, this);
                if (bussiness == null) throw new Exception("无法实例化IBusiness类型" + type.FullName);
                businessList.Add(bussiness);

            }

            return bussiness;
        }

        #region DBACCESS

        /// <summary>
        /// 手动开启事务，用于有事务和没事务混合的过程，如果整个访问过程都在一个事务，请使用DBContext(True)
        /// 如果前面有事务，会提交
        /// <param name="commitIfExistsTran">如果已经存在事务，是否先提交</param>
        /// </summary>
        public void BeginTransaction(bool commitIfExistsTran = true)
        {
            if (useTran)
            {
                if (commitIfExistsTran)
                {
                    LogMessage("有没提交的事务，自动提交", "DataBase");
                    this.Commit();
                }
                else
                {
                    LogMessage("有没提交的事务，不重复开启", "DataBase");
                    return;
                }
            }
            GetDBAccess().BeginTransaction();
            useTran = true;
        }
        public DataTable QueryTable(string text, CommandType cmdType, params IDbDataParameter[] parameters)
        {
            return GetDBAccess().QueryTable(text, cmdType, parameters);
        }
        public DataTable QueryTable(string sql)
        {
            return GetDBAccess().QueryTable(sql);
        }

        public IDataReader QueryReader(string sql)
        {
            return GetDBAccess().QueryReader(sql, CommandType.Text, null);
        }

        public IDataReader QueryReader(string sql, CommandType cmdType, params IDbDataParameter[] parameters)
        {
            return GetDBAccess().QueryReader(sql, cmdType, parameters);
        }

        /// <summary>
        /// 查询一列，拼接字符串
        /// </summary>
        public string QueryStringJoin(string sql, char ch = ',')
        {
            string result = "";
            using (IDataReader reader = QueryReader(sql))
            {
                while (reader.Read())
                {
                    result += ch + reader[0].ToString();
                }
                reader.Close();
            }
            if (result.Length > 0) result = result.Substring(1);
            return result;
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="select"></param>
        /// <param name="table"></param>
        /// <param name="where"></param>
        /// <param name="orderby"></param>
        /// <param name="start">起始位置，从1开始</param>
        /// <param name="end">结束位置</param>
        /// <returns></returns>
        public DataTable PartQuery(string select, string table, string where, string orderby, int start, int end)
        {
            string sql = GetDBAccess().PartQuerySql(select, table, where, orderby, start, end);
            return QueryTable(sql, CommandType.Text, null);
        }

        public int ExecuteCommand(string text, CommandType cmdType, params IDbDataParameter[] parameters)
        {
            return GetDBAccess().ExecuteCommand(text, cmdType, parameters);
        }
        public int ExecuteCommand(string sql)
        {
            return GetDBAccess().ExecuteCommand(sql);
        }

        public object ExecScalar(string text, CommandType cmdType, params IDbDataParameter[] parameters)
        {
            return GetDBAccess().ExecScalar(text, cmdType, parameters);
        }

        /// <summary>
        /// 执行语句返回第一行第一列，如果是空则为DBNull.Value(注意：不是null)
        /// </summary>
        /// <param name="sql"></param>
        /// <returns>第一行第一列值</returns>
        public object ExecScalar(string sql)
        {
            return GetDBAccess().ExecScalar(sql);
        }

        /// <summary>
        /// 查询某个字段的值
        /// </summary>        
        /// <param name="fieldName">字段名</param>
        /// <param name="primaryKey">主键值</param>
        /// <returns>如果字段为空则返回null(注意：不是DBNull.Value)</returns>
        public object ExecScalar<T>(string fieldName, int primaryKey)
        {
            Type entityType = typeof(T);
            QueryParam param = new QueryParam() { StrictModel = false, entityType = entityType, permission = null, queryField = fieldName };
            // param.whereJson = "{" + param.LoaderInfo.PrimaryCusPro.Info.Name + ":'" + primaryKey + "'}";
            param.AddWhere(param.LoaderInfo.PrimaryCusPro.Info.Name, primaryKey);
            var queryInstance = SetQueryEntityConfig(param);
            string sql;
            IDbDataParameter[] parameters;
            ParseQuerySql(queryInstance, out sql, out parameters);
            object scalar = GetDBAccess().ExecScalar(sql, CommandType.Text, parameters);
            if (scalar == DBNull.Value) return null;
            return scalar;
        }

        /// <summary>
        /// 查询某个字段的值，如果字段为空则返回null(注意：不是DBNull.Value)
        /// </summary>        
        /// <param name="fieldName">字段名</param>
        /// <param name="primaryKey">主键值</param>
        public object ExecScalar<T>(string fieldName, object where, string throwNull)
        {
            return ExecScalar<T>(null, fieldName, where, throwNull);
        }

        /// <summary>
        /// 查询某个字段的值,如果字段为空则返回null(注意：不是DBNull.Value)
        /// </summary>   
        /// <param name="fieldName">字段名</param>
        /// <param name="where">查询条件动态类</param>
        /// <param name="throwNull">如果空，抛出的异常信息</param>
        public object ExecScalar<T>(string permission, string fieldName, object where, string throwNull)
        {
            Type entityType = typeof(T);
            QueryParam param = new QueryParam() { StrictModel = false, entityType = entityType, permission = permission, queryField = fieldName };
            param.SetWhere(where);
            var queryInstance = SetQueryEntityConfig(param);
            string sql;
            IDbDataParameter[] parameters;
            ParseQuerySql(queryInstance, out sql, out parameters);
            object scalar = GetDBAccess().ExecScalar(sql, CommandType.Text, parameters);
            if (scalar == null || scalar == DBNull.Value)
            {
                if (throwNull != null) throw new ClientException(throwNull);
                return null;
            }
            return scalar;
        }

        /// <summary>
        /// 创建参数
        /// </summary>
        /// <returns></returns>
        public IDbDataParameter CreateParameter(string name, object value)
        {
            return GetDBAccess().CreateParameter(name, value);
        }

        /// <summary>
        /// 关闭连接，如果有事务则提交
        /// </summary>
        /// <returns></returns>
        public void Close()
        {
            if (m_dbAccess != null)
            {
                if (useTran)
                {
                    m_dbAccess.Commit();
                    useTran = false;
                }
                m_dbAccess.Close();
            }
            if (_redisAccessList != null)
            {
                foreach (var redisAccess in _redisAccessList)
                {
                    redisAccess.Dispose();
                }
                _redisAccessList.Clear();
            }
            membership.OnDBContextClosed(this);

        }

        /// <summary>
        /// 是否要在事务中
        /// </summary>
        public void RequireTransact(bool require = true)
        {
            if (require != useTran)
            {
                throw new ClientException("该过程" + (require ? "必需" : "不允许") + "在事务中执行");
            }
        }

        public void Rollback()
        {
            GetDBAccess().Rollback();
            useTran = false;
        }
        public void Commit()
        {
            GetDBAccess().Commit();
            useTran = false;
        }

        #endregion


        public void ChearCacheLike(string keyPatten)
        {
            keyPatten = membership.OnCacheKey(keyPatten);
            var entries = DBContext.Cache.GetType().GetField("_entries", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(DBContext.Cache);
            var cacheItems = entries as IDictionary;
            var keys = new List<string>();
            if (cacheItems != null)
            {
                foreach (DictionaryEntry cacheItem in cacheItems)
                {
                    keys.Add(cacheItem.Key.ToString());
                }
                foreach (string key in keys)
                {
                    if (key.IndexOf(keyPatten) > -1)
                    {
                        DBContext.Cache.Remove(key);
                    }
                }
            }
        }

        public static void ChearCache()
        {
            var entries = DBContext.Cache.GetType().GetField("_entries", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(DBContext.Cache);
            var cacheItems = entries as IDictionary;
            var keys = new List<string>();
            if (cacheItems != null)
            {
                foreach (DictionaryEntry cacheItem in cacheItems)
                {
                    keys.Add(cacheItem.Key.ToString());
                }
                foreach (string key in keys)
                {
                    DBContext.Cache.Remove(key);

                }
            }
        }

        public void UnLockOne(string lockItem)
        {
            RemoveLockItem(lockItem);
            if (current_lockItems == null) return;
            current_lockItems.Remove(lockItem);

        }

        private void RemoveLockItem(string lockItem)
        {
            if (UserRedis)
            {
                DeleteRedisItem(lockItem);
                // dlm.Unlock(ki.Value);
            }
            else lockQueue.Remove(lockItem);
        }
        public void UnLock()
        {
            if (current_lockItems != null)
            {
                foreach (string key in current_lockItems)
                {
                    RemoveLockItem(key);
                }
                current_lockItems.Clear();
                current_lockItems = null;
            }
        }

        /// <summary>
        /// 释放，如果有未提交的事务，则rollback，有未关闭的连接则close
        /// </summary>
        public void Dispose()
        {
            UnLock();
            if (businessList != null)
            {
                foreach (IBusiness business in businessList)
                {
                    if (business is IDisposable)
                    {
                        ((IDisposable)business).Dispose();
                    }
                }
                businessList.Clear();
            }
            if (m_dbAccess != null)
            {
                this.Rollback();
                m_dbAccess.Dispose();
            }
            if (_redisAccessList != null)
            {
                foreach (var redisAccess in _redisAccessList)
                {
                    redisAccess.Dispose();
                }
                _redisAccessList.Clear();
            }
            membership.OnDBContextDisposed(this);

        }


        public MyHttpUtility NewHttpUtility(int timeoutSecond = 0)
        {
            return new MyHttpUtility(this, timeoutSecond);
        }

        public MyHttpUtility NewHttpUtility(System.Net.SecurityProtocolType spt, System.Text.Encoding encoding, int timeoutSecond = 0)
        {
            MyHttpUtility http = new MyHttpUtility(this, timeoutSecond);
            http.TextEncoding = encoding;
            http.SecurityProtocolType = spt;
            return http;
        }

        public DBContext Clone()
        {
            DBContext newContext = new DBContext();
            newContext.currentDBContextConfig = this.GetConfig();
            newContext.membership = this.Membership;
            if (this.OEM != null) newContext.SetArgument("OEMInfo", this.OEM);
            return newContext;
        }
    }


}